Multiton pattern

Multiton pattern

In software engineering, the multiton pattern is a design pattern similar to the singleton, which allows only one instance of a class to be created. The multiton pattern expands on the singleton concept to manage a map of named instances as key-value pairs.

Rather than have a single instance per application (e.g. the java.lang.Runtime object in the Java programming language) the multiton pattern instead ensures a single instance per key.

Most people and textbooks consider this a singleton pattern. For example, multiton does not explicitly appear in the highly-regarded object-oriented programming text book Design Patterns (it appears as a more flexible approach named Registry of singletons).

Contents

Example

An example thread-safe Java implementation follows:

Java

The first example synchronizes the whole getInstance()-method (which may be expensive in a highly concurrent environment).

    public class FooMultiton {
        private static final Map<Object, FooMultiton> instances = new HashMap<Object, FooMultiton>();
 
        private FooMultiton() /* also acceptable: protected, {default} */ {
            /* no explicit implementation */
        }
 
        public static FooMultiton getInstance(Object key) {
            synchronized (instances) {
 
                // Our "per key" singleton
                FooMultiton instance = instances.get(key);
 
                if (instance == null) {
 
                    // Lazily create instance
                    instance = new FooMultiton();
 
                    // Add it to map   
                    instances.put(key, instance);
                }
 
                return instance;
            }
        }
 
        // other fields and methods ...
 
    }

To avoid this (expensive) synchronization for many reader-threads in a highly concurrent environment one may also combine the multiton pattern with double-checked locking:

    public class FooMultiton {
       private static final Map<Object, FooMultiton> instances = new HashMap<Object, FooMultiton>();
 
       private FooMultiton() /* also acceptable: protected, {default} */ {
            /* no explicit implementation */
        }
 
        public static FooMultiton getInstance(Object key) {
            // Our "per key" singleton
            FooMultiton instance = instances.get(key);
 
            // if the instance has never been created ...
            if (instance == null) {
                synchronized (instances) {
 
                    // Check again, after having acquired the lock to make sure 
                    // the instance was not created meanwhile by another thread
                    instance = instances.get(key);
 
                    if (instance == null) {
                        // Lazily create instance
                        instance = new FooMultiton();
 
                        // Add it to map   
                        instances.put(key, instance);
                    }
                }
            }
            return instance;
        }
 
        // other fields and methods ...
 
    }

C#

using System.Collections.Generic;
 
namespace MyApplication {
    class FooMultiton {
        private static readonly Dictionary<object, FooMultiton> _instances = new Dictionary<object, FooMultiton>();
 
        private FooMultiton() {
        }
 
        public static FooMultiton GetInstance(object key) {
            lock (_instances) {   
                FooMultiton instance;
                if (!_instances.TryGetValue(key, out instance)) {
                    instance = new FooMultiton();
                    _instances.Add(key, instance);
                }
                return instance;
            }
        }
    }
}

Python

class Multiton(object):
    def __init__(self):
        self.instances = {}
 
    def __call__(self, key, instance):
        self.instances[key] = instance
        return instance
 
    def get_instance(self, key):
        return self.instances[key]
 
class A(object):
    def __init__(self, *args, **kw):
        pass
 
m = Multiton()
a0 = m('a0', A())
a1 = m('a1', A())
print m.get_instance('a0')
print m.get_instance('a1')

Python (using decorators)

def multiton(cls):
    instances = {}
    def getinstance(name):
        if name not in instances:
            instances[name] = cls()
        return instances[name]
    return getinstance
 
@multiton
class MyClass:
    ...
 
a=MyClass("MyClass0")
b=MyClass("MyClass0")
c=MyClass("MyClass1")
print a is b #True
print a is c #False

PHP

<?php
//orochi
// This example requires php 5.3+
abstract class Multiton {
    private static $instances = array();
    public static function getInstance() {
        // For non-complex construction arguments, you can just use the $arg as the key
                $key = get_called_class() . serialize(func_get_args());
                if (!isset(self::$instances[$key])) {
                // You can do this without the reflection class if you want to hard code the class constructor arguments
                        $rc = new ReflectionClass(get_called_class());
                        self::$instances[$key] = $rc->newInstanceArgs(func_get_args());
                }
                return self::$instances[$key];
    }
}
 
class Hello extends Multiton {
        public function __construct($string = 'world') {
                echo "Hello $string\n";
        }
}
 
class GoodBye extends Multiton {
        public function __construct($string = 'my', $string2 = 'darling') {
                echo "Goodbye $string $string2\n";
        }
}
 
$a = Hello::getInstance('world');
 
$b = Hello::getInstance('bob');
// $a !== $b
 
$c = Hello::getInstance('world');
// $a === $c
 
$d = GoodBye::getInstance();
 
$e = GoodBye::getInstance();
// $d === $e
 
$f = GoodBye::getInstance('your');
// $d !== $f

Action Script 3.0/ Flex

    import flash.utils.Dictionary;
 
    public class InternalModelLocator {
                private static var instances:Dictionary = new Dictionary();
 
                public function InternalModelLocator() {
                   /* Only one instance created with GetInstanceMethod*/
                }
 
 
                /* module_uuid can be a String -------- 
                   In case of PureMVC "multitonKey" (this.multitonKey) can be used as unique key for multiple modules
                */
                public static function getInstance(module_uuid:String):InternalModelLocator {
                        var instance:InternalModelLocator = instances[module_uuid];
 
                        if (instance == null) {
                                instance = new InternalModelLocator();
                                instances[module_uuid] = instance;
                        }
                        return instance;
                } 
        }

C++

Implementation from StackOverflow

#ifndef MULTITON_H
#define MULTITON_H
 
#include <map>
 
template <typename Key, typename T> class Multiton {
public:    
    static void destroy() {
        for (typename std::map<Key, T*>::iterator it = instances.begin(); it != instances.end(); ++it) {
            delete (*it).second;
        }
    }
 
    static T& getRef(const Key& key) {
        typename std::map<Key, T*>::iterator it = instances.find(key);
 
        if (it != instances.end()) {
            return *(T*)(it->second);
        }
 
        T* instance = new T;
        instances[key] = instance;
        return *instance;
    }
 
    static T* getPtr(const Key& key) {
        typename std::map<Key, T*>::iterator it = instances.find(key);
 
        if (it != instances.end()) {
            return (T*)(it->second);
        }
 
        T* instance = new T;
        instances[key] = instance;
        return instance;
    }
 
protected:
    Multiton() {}
    virtual ~Multiton() {}
 
private:
    Multiton(const Multiton&) {}
    Multiton& operator= (const Multiton&) { return *this; }
 
    static std::map<Key, T*> instances;
};
 
template <typename Key, typename T> std::map<Key, T*> Multiton<Key, T>::instances;
 
#endif

Usage:

class Foo : public Multiton<std::string, Foo> {};
Foo& foo1 = Foo::getRef("foobar");
Foo* foo2 = Foo::getPtr("foobar");
Foo::destroy();

Clarification of example code

While it may appear that the multiton is no more than a simple hash table with synchronized access there are two important distinctions. First, the multiton does not allow clients to add mappings. Secondly, the multiton never returns a null or empty reference; instead, it creates and stores a multiton instance on the first request with the associated key. Subsequent requests with the same key return the original instance. A hash table is merely an implementation detail and not the only possible approach. The pattern simplifies retrieval of shared objects in an application.

Since the object pool is created only once, being a member associated with the class (instead of the instance), the multiton retains its flat behavior rather than evolving into a tree structure.

The multiton is unique in that it provides centralized access to a single directory (i.e. all keys are in the same namespace, per se) of multitons, where each multiton instance in the pool may exist having its own state. In this manner, the pattern advocates indexed storage of essential objects for the system (such as would be provided by an LDAP system, for example). However, a multiton is limited to wide use by a single system rather than a myriad of distributed systems.

Drawbacks

This pattern, like the Singleton pattern, makes unit testing far more difficult[1], as it introduces global state into an application.

With garbage collected languages it may become a source of memory leaks as it introduces global strong references to the objects.

References

External links


Wikimedia Foundation. 2010.

Игры ⚽ Нужно решить контрольную?

Look at other dictionaries:

  • multiton — 1. adjective Weighing more than one ton. 2. noun A design pattern resembling the singleton pattern except that multiple keyed instances of the class can be created …   Wiktionary

  • Software design pattern — In software engineering, a design pattern is a general reusable solution to a commonly occurring problem within a given context in software design. A design pattern is not a finished design that can be transformed directly into code. It is a… …   Wikipedia

  • Singleton pattern — In software engineering, the singleton pattern is a design pattern used to implement the mathematical concept of a singleton, by restricting the instantiation of a class to one object. This is useful when exactly one object is needed to… …   Wikipedia

  • Singleton Pattern — Das Singleton (auch Einzelstück genannt) ist ein in der Softwareentwicklung eingesetztes Entwurfsmuster und gehört zur Kategorie der Erzeugungsmuster (engl. Creational Patterns). Es verhindert, dass von einer Klasse mehr als ein Objekt erzeugt… …   Deutsch Wikipedia

  • Шаблон проектирования — У этого термина существуют и другие значения, см. Паттерн. В разработке программного обеспечения, шаблон проектирования или паттерн (англ. design pattern) повторимая архитектурная конструкция, представляющая собой решение проблемы… …   Википедия

  • 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 maintaining a flag… …   Wikipedia

  • Initialization on demand holder idiom — In software engineering, the Initialization on Demand Holder idiom (design pattern) is a lazy loaded singleton. The idiom can be implemented in both single threaded/serial and concurrent environments, but care must be taken to correctly implement …   Wikipedia

  • Einzelstück (Entwurfsmuster) — Das Singleton (auch Einzelstück genannt) ist ein in der Softwareentwicklung eingesetztes Entwurfsmuster und gehört zur Kategorie der Erzeugungsmuster (engl. Creational Patterns). Es verhindert, dass von einer Klasse mehr als ein Objekt erzeugt… …   Deutsch Wikipedia

  • Singleton (Entwurfsmuster) — Das Singleton (auch Einzelstück genannt) ist ein in der Softwareentwicklung eingesetztes Entwurfsmuster und gehört zur Kategorie der Erzeugungsmuster (engl. Creational Patterns). Es verhindert, dass von einer Klasse mehr als ein Objekt erzeugt… …   Deutsch Wikipedia

  • aerospace industry — Introduction       assemblage of manufacturing concerns that deal with vehicular flight within and beyond the Earth s atmosphere. (The term aerospace is derived from the words aeronautics and spaceflight.) The aerospace industry is engaged in the …   Universalium

Share the article and excerpts

Direct link
Do a right-click on the link above
and select “Copy Link”