Lazy initialization

In computer programming, lazy initialization is the tactic of delaying the creation of an object, the calculation of a value, or some other expensive process until the first time it is needed.

This is typically accomplished by augmenting a variable's accessor method (or property definition) to check for a previously-created instance. If none exists a new instance is created, placed into the variable, and this new object is returned to the caller in a just-in-time fashion. In this manner object creation is deferred until first use which can, in some circumstances (e.g., sporadic object access), increase system responsiveness and speed startup by bypassing large-scale object pre-allocation. (Note that this may have attendant counter-effects on overall performance, however, as the impact of object instantiation is then amortized across the startup/warm-up phase of the system.)

In multithreaded code, access to lazy-initialized objects/state must be synchronized to guard against a race condition.

See lazy evaluation for a general treatment of this idea. In heavily imperative languages this pattern carries hidden dangers, as does any programming habit that relies on shared state.

The "lazy factory"

In a software design pattern view, lazy initialization is often used together with a factory method pattern. This combines three ideas:

Examples

Actionscript 3

The following is an example of a class with Lazy initialization implemented in Actionscript:

package examples.lazyinstantiation
{
	public class Fruit 
	{
		private var _typeName:String;
		private static var instancesByTypeName:Dictionary = new Dictionary();
	 
		public function Fruit(typeName:String):void
		{
			this._typeName = typeName;
		}
		
		public function get typeName():String 
		{
			return _typeName;
		}
	 
		public static function getFruitByTypeName(typeName:String):Fruit
		{
			return instancesByTypeName[typeName] ||= new Fruit(typeName);
		}
	 
		public static function printCurrentTypes():void
		{
			for each (var fruit:Fruit in instancesByTypeName) 
			{
				// iterates through each value
				trace(fruit.typeName);
			}
		}
	}
}

Basic Usage:

package
{
	import examples.lazyinstantiation;
	
	public class Main 
	{
		public function Main():void
		{
			Fruit.getFruitByTypeName("Banana");
			Fruit.printCurrentTypes();
	 
			Fruit.getFruitByTypeName("Apple");
			Fruit.printCurrentTypes();
	 
			Fruit.getFruitByTypeName("Banana");
			Fruit.printCurrentTypes();
		}
	}
}

C

In C, lazy evaluation would normally be implemented inside a single function, or a single source file, using static variables.

In a function:

#include <string.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>

struct fruit {
    char *name;
    struct fruit *next;
    int number;
    /* Other members */
};

struct fruit *get_fruit(char *name) {
    static struct fruit *fruit_list;
    static int seq;
    struct fruit *f;
    for (f = fruit_list; f; f = f->next)
        if (0 == strcmp(name, f->name))
            return f;
    if (!(f = malloc(sizeof(struct fruit))))
        return NULL;
    if (!(f->name = strdup(name))) {
        free(f);
        return NULL;
    }
    f->number = ++seq;
    f->next = fruit_list;
    fruit_list = f;
    return f;
}

/* Example code */

int main(int argc, char *argv[]) {
    int i;
    struct fruit *f;
    if (argc < 2) {
        fprintf(stderr, "Usage: fruits fruit-name [...]\n");
        exit(1);
    }
    for (i = 1; i < argc; i++) {
        if ((f = get_fruit(argv[i]))) {
            printf("Fruit %s: number %d\n", argv[i], f->number);
        }
    }
    return 0;
}

Using a single source file instead allows the state to be shared between multiple functions, while still hiding it from non-related functions.

fruit.h:

#ifndef _FRUIT_INCLUDED_
#define _FRUIT_INCLUDED_

struct fruit {
    char *name;
    struct fruit *next;
    int number;
    /* Other members */
};

struct fruit *get_fruit(char *name);
void print_fruit_list(FILE *file);

#endif /* _FRUIT_INCLUDED_ */

fruit.c:

#include <string.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include "fruit.h"

static struct fruit *fruit_list;
static int seq;

struct fruit *get_fruit(char *name) {
    struct fruit *f;
    for (f = fruit_list; f; f = f->next)
        if (0 == strcmp(name, f->name))
            return f;
    if (!(f = malloc(sizeof(struct fruit))))
        return NULL;
    if (!(f->name = strdup(name))) {
        free(f);
        return NULL;
    }
    f->number = ++seq;
    f->next = fruit_list;
    fruit_list = f;
    return f;
}

void print_fruit_list(FILE *file) {
    struct fruit *f;
    for (f = fruit_list; f; f = f->next)
        fprintf(file, "%4d  %s\n", f->number, f->name);
}

main.c:

#include <stdlib.h>
#include <stdio.h>
#include "fruit.h"

int main(int argc, char *argv[]) {
    int i;
    struct fruit *f;
    if (argc < 2) {
        fprintf(stderr, "Usage: fruits fruit-name [...]\n");
        exit(1);
    }
    for (i = 1; i < argc; i++) {
        if ((f = get_fruit(argv[i]))) {
            printf("Fruit %s: number %d\n", argv[i], f->number);
        }
    }
    printf("The following fruits have been generated:\n");
    print_fruit_list(stdout);
    return 0;
}

C#

In .NET 4.0 Microsoft has included a Lazy class that can be used to do lazy loading. Below is some dummy code that does lazy loading of Class Fruit

Lazy<Fruit> lazyFruit = new Lazy<Fruit>();
Fruit fruit = lazyFruit.Value;

Here is a dummy example in C#.

The Fruit class itself doesn't do anything here, The class variable _typesDictionary is a Dictionary/Map used to store Fruit instances by typeName.

using System;
using System.Collections;
using System.Collections.Generic;

public class Fruit
{
    private string _typeName;
    private static Dictionary<string, Fruit> _typesDictionary = new Dictionary<string, Fruit>();

    private Fruit(String typeName)
    {
        this._typeName = typeName;
    }

    public static Fruit GetFruitByTypeName(string type)
    {
        Fruit fruit;

        if (!_typesDictionary.TryGetValue(type, out fruit))
        {
            // Lazy initialization
            fruit = new Fruit(type);

            _typesDictionary.Add(type, fruit);
        }
        return fruit;
    }

    public static void ShowAll()
    {
        if (_typesDictionary.Count > 0)
        {
            Console.WriteLine("Number of instances made = {0}", _typesDictionary.Count);
            
            foreach (KeyValuePair<string, Fruit> kvp in _typesDictionary)
            {
                Console.WriteLine(kvp.Key);
            }
            
            Console.WriteLine();
        }
    }
    
    public Fruit()
    {
        // required so the sample compiles
    }
}

class Program
{
    static void Main(string[] args)
    {
        Fruit.GetFruitByTypeName("Banana");
        Fruit.ShowAll();

        Fruit.GetFruitByTypeName("Apple");
        Fruit.ShowAll();

        // returns pre-existing instance from first 
        // time Fruit with "Banana" was created
        Fruit.GetFruitByTypeName("Banana");
        Fruit.ShowAll();

        Console.ReadLine();
    }
}

A fairly straightforward 'fill-in-the-blanks' example of a Lazy Initialization design pattern, except that this uses an enumeration for the type

namespace DesignPatterns.LazyInitialization
{
    public class LazyFactoryObject
    {
        //internal collection of items
        //IDictionaery makes sure they are unique
        private IDictionary<LazyObjectType, LazyObject> _LazyObjectList = 
            new Dictionary<LazyObjectType, LazyObject>();

        //enum for passing name of type required
        //avoids passing strings and is part of type ahead
        public enum LazyObjectType
        { 
            None,
            Small,
            Big,
            Bigger,
            Huge
        }

        //standard type of object that will be constructed
        public struct LazyObject
        {
            public LazyObjectType Name;
            public IList<int> Result;
        }

        //takes type and create 'expensive' list
        private IList<int> Result(LazyObjectType name)
        {
            IList<int> result = null;

            switch (name)
            { 
                case LazyObjectType.Small:
                    result = CreateSomeExpensiveList(1, 100);
                    break;
                case LazyObjectType.Big:
                    result = CreateSomeExpensiveList(1, 1000);
                    break;
                case LazyObjectType.Bigger:
                    result = CreateSomeExpensiveList(1, 10000);
                    break;
                case LazyObjectType.Huge:
                    result = CreateSomeExpensiveList(1, 100000);
                    break;
                case LazyObjectType.None:
                    result = null;
                    break;
                default:
                    result = null;
                    break;
            }

            return result;
        }

        //not an expensive item to create, but you get the point
        //delays creation of some expensive object until needed
        private IList<int> CreateSomeExpensiveList(int start, int end)
        {
            IList<int> result = new List<int>();

            for (int counter = 0; counter < (end - start); counter++)
            {
                result.Add(start + counter);
            }

            return result;
        }

        public LazyFactoryObject()
        { 
            //empty constructor
        }

        public LazyObject GetLazyFactoryObject(LazyObjectType name)
        {
            //yes, i know it is illiterate and inaccurate
            LazyObject noGoodSomeOne;

            //retrieves LazyObjectType from list via out, else creates one and adds it to list
            if (!_LazyObjectList.TryGetValue(name, out noGoodSomeOne))
            {
                noGoodSomeOne = new LazyObject();
                noGoodSomeOne.Name = name;
                noGoodSomeOne.Result = this.Result(name);

                _LazyObjectList.Add(name, noGoodSomeOne);
            }

            return noGoodSomeOne;
        }
    }
}

C++

Here is an example in C++.

#include <iostream>
#include <string>
#include <map>
 
using namespace std;
 
class Fruit {
    public:
        static Fruit* getFruit(const string& type);
        static void printCurrentTypes();

    private:
        static map<string,Fruit*> types;
        string type;

        // note: constructor private forcing one to use static getFruit()
        Fruit(const string& t) : type( t ) {}
};

//definition 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) {
    map<string,Fruit*>::iterator it = types.find(type);  // try to find an existing instance; if not found std::map will return types.end()
 
    Fruit *f;
    if (it == types.end()) { // if no instance with the proper type was found, make one
        f = new Fruit(type); // lazy initialization part
        types[type] = f;     // adding the newly created Fruit to the types map for later lookup
    } else { //if already had an instance
        f = it->second; //The return value will be the found fruit
    }
    return f;
}

/*
 * For example purposes to see pattern in action
 */
void Fruit::printCurrentTypes() {
    if (!types.empty()) {
        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
*/

Java

Here is an example in Java.

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

public class Program {

    /**
     * @param args
     */
    public static void main(String[] args) {
        Fruit.getFruitByTypeName(FruitType.banana);
        Fruit.showAll();
        Fruit.getFruitByTypeName(FruitType.apple);
        Fruit.showAll();
        Fruit.getFruitByTypeName(FruitType.banana);
        Fruit.showAll();
    }
}

enum FruitType {
    none,
    apple,
    banana,
}

class Fruit {

    private static Map<FruitType, Fruit> types = new HashMap<>();
    
    /**
     * Using a private constructor to force the use of the factory method.
     * @param type
     */
    private Fruit(FruitType type) {
    }
    
    /**
     * Lazy Factory method, gets the Fruit instance associated with a certain
     * type. Instantiates new ones as needed.
     * @param type Any allowed fruit type, e.g. APPLE
     * @return The Fruit instance associated with that type.
     */
    public static Fruit getFruitByTypeName(FruitType type) {
        Fruit fruit;
                // This has concurrency issues.  Here the read to types is not synchronized, 
                // so types.put and types.containsKey might be called at the same time.
                // Don't be surprised if the data is corrupted.
        if (!types.containsKey(type)) {
            // Lazy initialisation
            fruit = new Fruit(type);
            types.put(type, fruit);
        } else {
            // OK, it's available currently
            fruit = types.get(type);
        }
        
        return fruit;
    }
    
    /**
     * Lazy Factory method, gets the Fruit instance associated with a certain
     * type. Instantiates new ones as needed. Uses double-checked locking 
     * pattern for using in highly concurrent environments.
     * @param type Any allowed fruit type, e.g. APPLE
     * @return The Fruit instance associated with that type.
     */
    public static Fruit getFruitByTypeNameHighConcurrentVersion(FruitType type) {
        if (!types.containsKey(type)) {
            synchronized (types) {
                // Check again, after having acquired the lock to make sure
                // the instance was not created meanwhile by another thread
                if (!types.containsKey(type)) {
                    // Lazy initialisation
                    types.put(type, new Fruit(type));
                }
            }
        }
        
        return types.get(type);
    }
    
    /**
     * Displays all entered fruits.
     */
    public static void showAll() {
        if (types.size() > 0) {
 
           System.out.println("Number of instances made = " + types.size());
            
            for (Entry<FruitType, Fruit> entry : types.entrySet()) {
                String fruit = entry.getKey().toString();
                fruit = Character.toUpperCase(fruit.charAt(0)) + fruit.substring(1);
                System.out.println(fruit);
            }
            
            System.out.println();
        }
    }
}

Output

Number of instances made = 1
Banana

Number of instances made = 2
Banana
Apple

Number of instances made = 2
Banana
Apple

JavaScript

Here is an example in JavaScript.

var Fruit = (function() {
  var types = {};
  function Fruit() {};

  // count own properties in object
  function count(obj) {
    return Object.keys(obj).length;
  }

  var _static = {
    getFruit: function(type) {
      if (typeof 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();

Output

Number of instances made: 1
Apple

Number of instances made: 2
Apple
Banana

Number of instances made: 2
Apple
Banana

PHP

Here is an example of lazy initialization in PHP 5:

<?php
header('Content-type:text/plain; charset=utf-8');

class Fruit {
    private $type;
    private static $types = array();

    private function __construct($type) {
        $this->type = $type;
    }

    public static function getFruit($type) {
        // Lazy initialization takes place here
        if (!isset(self::$types[$type])) {
            self::$types[$type] = new Fruit($type);
        }

        return self::$types[$type];
    }

    public static function printCurrentTypes() {
        echo 'Number of instances made: ' . count(self::$types) . "\n";
        foreach (array_keys(self::$types) as $key) {
            echo "$key\n";
        }
        echo "\n";
    }
}

Fruit::getFruit('Apple');
Fruit::printCurrentTypes();

Fruit::getFruit('Banana');
Fruit::printCurrentTypes();

Fruit::getFruit('Apple');
Fruit::printCurrentTypes();

/*
OUTPUT:

Number of instances made: 1
Apple

Number of instances made: 2
Apple
Banana

Number of instances made: 2
Apple
Banana
*/

?>

Python

Here is an example in Python.

class Fruit:
    def __init__(self, item):
        self.item = item
    
class Fruits:
    def __init__(self):
        self.items = {}
    
    def get_fruit(self, item):
        if item not in self.items:
            self.items[item] = Fruit(item)
        
        return self.items[item]

if __name__ == '__main__':
    fruits = Fruits()
    print(fruits.get_fruit('Apple'))
    print(fruits.get_fruit('Lime'))

Ruby

Here is an example in Ruby, of lazily initializing an authentication token from a remote service like Google. The way that @auth_token is cached is also an example of memoization.

require 'net/http'
class Blogger
  def auth_token
    @auth_token ||=
      (res = Net::HTTP.post_form(uri, params)) &&
      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

Smalltalk

Here is an example in Smalltalk, of a typical accessor method to return the value of a variable using lazy initialization.

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

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.

Scala

Scala has built-in support for lazy variable initiation.[1]

 scala> val x = { println("Hello"); 99 }
 Hello
 x: Int = 99
 scala> lazy val y = { println("Hello!!"); 31 }
 y: Int = <lazy>
 scala> y
 Hello!!
 res2: Int = 31
 scala> y
 res3: Int = 31

See also

References

External links

This article is issued from Wikipedia - version of the 10/29/2016. The text is available under the Creative Commons Attribution/Share Alike but additional terms may apply for the media files.