Късна инициализация (шаблон)

от Уикипедия, свободната енциклопедия
Направо към: навигация, търсене

Късна инициализация (Lazy initialization) е създаващ шаблон за дизайн, който се използва в обектно-ориентираното програмиране.

Целта на късната инициализация е да се отложи във времето създаването на обект, изчисляването на стойност или на някакъв друг отнемащ ресурси процес, до момента в който не ни е нужен за първи път.


Примери[редактиране | edit source]

Java[редактиране | edit source]

import java.util.*;
 
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);
    }
}

C#[редактиране | edit source]

Същия пример за C#

using System;
using System.Collections.Generic;
 
public class Fruit
{
    private static Dictionary<string,Fruit> types = new Dictionary<string,Fruit>();
    private string type;
 
    /// <summary>
    /// using a private constructor to force use of the factory method.
    /// </summary>
    /// <param name="type">Type of fruit</param>
    private Fruit(String type) {
      this.type = type;
    }
 
    /// </summary>
    /// <param name="type">Any string that describes a fruit type, e.g. "apple"</param>
    /// <returns>The Fruit instance associated with that type.</returns>
    public static Fruit getFruit(string type) {
        Fruit f;
 
        if ( ! types.TryGetValue(type, out f) )
        {
          f = new Fruit(type); // lazy initialization
          types.Add(type,f);
        }
 
      return f;
    }
 
    public static void printCurrentTypes() {
        if (types.Count > 0) {
            Console.WriteLine("Number of instances made = {0}",types.Count);
            foreach (KeyValuePair<string,Fruit> kvp in types) 
            {
                Console.WriteLine(kvp.Key);
            }
            Console.WriteLine();
        }
    }
 
}
 
 
 
class Program
{
    static void Main(string[] args)
    {
        Fruit.getFruit("Banana");
        Fruit.printCurrentTypes();
 
        Fruit.getFruit("Apple");
        Fruit.printCurrentTypes();
 
        // returns pre-existing instance from first 
        // time Fruit with "Banana" was created
        Fruit.getFruit("Banana");
        Fruit.printCurrentTypes();
 
        Console.ReadLine();
    }
}

C++[редактиране | edit source]

#include <iostream>
#include <string>
#include <map>
 
using namespace std;
 
class Fruit {
    private:
        static map<string,Fruit*> types;
        string type;
 
        // note: constructor private forcing one to use static getFruit()
        Fruit(const string& t) : type( t ) {}
 
    public:
        static Fruit* getFruit(const string& type);
        static void printCurrentTypes();
};
 
//declaration needed for using any static member variable
map<string,Fruit*> Fruit::types;        
 
/*
 * Lazy Factory method, gets the Fruit instance associated with a
 * certain type. Instantiates new ones as needed.
 * precondition: type. Any string that describes a fruit type, e.g. "apple"
 * postcondition: The Fruit instance associated with that type.
 */
Fruit* Fruit::getFruit(const string& type) {
    Fruit *& f = types[type];   //try to find a pre-existing instance
 
    if (!f) {
        // couldn't find one, so make a new instance
        f = new Fruit(type); // lazy initialization part
    }
    return f;
}
 
/*
 * For example purposes to see pattern in action
 */
void Fruit::printCurrentTypes() {
    if (types.size() > 0) {
        cout << "Number of instances made = " << types.size() << endl;
        for (map<string,Fruit*>::iterator iter = types.begin(); iter != types.end(); ++iter) {
            cout << (*iter).first << endl;
        }
        cout << endl;
    }
}
 
int main(void) {
    Fruit::getFruit("Banana");
    Fruit::printCurrentTypes();
 
    Fruit::getFruit("Apple");
    Fruit::printCurrentTypes();
 
    // returns pre-existing instance from first 
    // time Fruit with "Banana" was created
    Fruit::getFruit("Banana");
    Fruit::printCurrentTypes();
 
    return 0;
}
 
 
 
/*
OUTPUT:
Number of instances made = 1
Banana
 
Number of instances made = 2
Apple
Banana
 
Number of instances made = 2
Apple
Banana
*/

SmallTalk[редактиране | edit source]

    height
        height ifNil: [height := 2.0].
        ^height

The 'non-lazy' alternative is to use an initialization method that is run when the object is created and then use a simpler accessor method to fetch the value.

    initialize
        height := 2.0
 
    height
        ^height

Note that lazy initialization can also be used in non-object-oriented languages.

Ruby[редактиране | edit source]

require 'net/http'
class Blogger
  def auth_token
    return @auth_token if @auth_token
 
    res = Net::HTTP.post_form(uri, params)
    @auth_token = get_token_from_http_response(res)
  end
 
  # get_token_from_http_response, uri and params are defined later in the class
end
 
b = Blogger.new
b.instance_variable_get(:@auth_token) # returns nil
b.auth_token # returns token
b.instance_variable_get(:@auth_token) # returns token

Вижте също[редактиране | edit source]

External links[редактиране | edit source]