Лінива ініціалізація

Відкладена (лінива) ініціалізація (англ. Lazy initialization) — прийом в програмуванні, коли деяка ресурсномістка операція (створення об'єкта, обчислення значення) виконується безпосередньо перед тим, як буде використаний її результат. Таким чином, ініціалізація виконується "на вимогу", а не завчасно. Аналогічна ідея знаходить застосування в самих різних галузях: наприклад, компіляція «на льоту» і логістична концепція «Точно в строк».

Фабрика відкладеної ініціалізації

[ред. | ред. код]

Шаблон проєктування «відкладена ініціалізація» часто використовують разом з шаблоном фабричного методу. Тут поєднані три ідеї:

  • використання фабричного методу для отримання екземпляра класу
  • збереження екземплярів у відображенні (Map), так що наступного разу можна запросити цей же екземпляр (Мультитон, Unit Of Work, тощо)
  • використання відкладеної ініціалізації для створення екземпляра об'єкта лише тоді, коли поступає запит

Приклади

[ред. | ред. код]
Приклад реалізації мовою C#
using System;

namespace LazyInitialization
{
    // важкий об'єкт
    class Biggy
    {
        public Biggy()
        {
            Console.WriteLine("Biggy is created");
        }
    }

    // реалізуємо ліниву ініціалізацію вручну
    class A
    {
        Biggy biggy;

        public A()
        {
            biggy = null;
            Console.WriteLine("A is created");

        }

        public Biggy GetBiggy
        {
            get
            {
                if (biggy == null) biggy = new Biggy();
                return biggy;
            }
        }           
    }

    // використаємо вбудований механізм
    class B
    {
        Lazy<Biggy> biggy;

        public B()
        {
            biggy = new Lazy<Biggy>();
            Console.WriteLine("B is created");

        }

        public Biggy GetBiggy => biggy.Value;
    }

    class Program
    {
        static void Main(string[] args)
        {
            // створюємо важкий об'єкт
            // лише при необхідності (непарні індекси)
            // і всі наступні запити використовують цей самий об'єкт
            A a = new A();
            for (int i = 0; i < 5; ++i)
            {
                if (i % 2 != 0)
                {
                    Console.WriteLine("= Need biggy =");
                    Biggy biggy = a.GetBiggy;
                }
                else
                {
                    Console.WriteLine("= No biggy needed =");
                }
            }

            Console.ReadLine();
        }
    }
}
Приклад реалізації мовою Java
public class Fruit {
 
    private static final Map<String,Fruit> types = new HashMap<String, Fruit>();
    private final String type;
 
    // using a private constructor to force use of the factory method.
    private Fruit(String type) {
        this.type = type;
    }
 
    /**
    * Lazy Factory method, gets the Fruit instance associated with a
    * certain type. Instantiates new ones as needed.
    * @param type Any string that describes a fruit type, e.g. "apple"
    * @return The Fruit instance associated with that type.
    */
    public static synchronized Fruit getFruit(String type) {
        if(!types.containsKey(type)) {
            types.put(type, new Fruit(type)); // Lazy initialization
        }
        return types.get(type);
    }
 
}

JavaScript

[ред. | ред. код]
Приклад реалізації мовою JavaScript
var Fruit = (function () {
 
  var types = {};
 
  function Fruit() {};
 
 
  // counts own properties in object
  function count(obj) {
    var i = 0;
    for (var key in obj) {
      if (obj.hasOwnProperty(key)) {
        i++;
      }
    }
 
    return i;
  }
 
  var _static = {
    getFruit: function (type) {
      if (types[type] === undefined) {
        types[type] = new Fruit;
      }
 
      return types[type];
    },
    printCurrentTypes: function () {
      console.log('Number of instances made: ' + count(types));
      for (var type in types) {
        console.log(type);
      }
    }
  };
 
  return _static;
 
})();
 
Fruit.getFruit('Apple');
Fruit.printCurrentTypes();
Fruit.getFruit('Banana');
Fruit.printCurrentTypes();
Fruit.getFruit('Apple');
Fruit.printCurrentTypes();


Посилання

[ред. | ред. код]