Multiton pattern
Encyclopedia
In software engineering
Software engineering
Software Engineering is the application of a systematic, disciplined, quantifiable approach to the development, operation, and maintenance of software, and the study of these approaches; that is, the application of engineering to software...

, the multiton pattern is a design pattern
Design pattern (computer science)
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 description or template for how to solve a problem that...

 similar to the singleton
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 coordinate actions across the system...

, which allows only one instance of a class to be created. The multiton pattern expands on the singleton concept to manage a map
Associative array
In computer science, an associative array is an abstract data type composed of a collection of pairs, such that each possible key appears at most once in the collection....

 of named instances as key-value pairs.

Rather than have a single instance per application (e.g. the object in the Java programming language
Java (programming language)
Java is a programming language originally developed by James Gosling at Sun Microsystems and released in 1995 as a core component of Sun Microsystems' Java platform. The language derives much of its syntax from C and C++ but has a simpler object model and fewer low-level facilities...

) 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
Object-oriented programming
Object-oriented programming is a programming paradigm using "objects" – data structures consisting of data fields and methods together with their interactions – to design applications and computer programs. Programming techniques may include features such as data abstraction,...

 text book Design Patterns (it appears as a more flexible approach named Registry of singletons).

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 instances = new HashMap;

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
Double-checked locking
In software engineering, double-checked locking is a software design pattern used to reduce the overhead of acquiring a lock by first testing the locking criterion without actually acquiring the lock...

:


public class FooMultiton {
private static final Map instances = new HashMap;

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 _instances = new Dictionary;

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


//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

  1. ifndef MULTITON_H
  2. define MULTITON_H

  1. include


template class Multiton {
public:
static void destroy {
for (typename std::map::iterator it = instances.begin; it != instances.end; ++it) {
delete (*it).second;
}
}

static T& getRef(const Key& key) {
typename std::map::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::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 instances;
};

template std::map Multiton::instances;
  1. endif



Usage:

class Foo : public Multiton {};
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
Hash table
In computer science, a hash table or hash map is a data structure that uses a hash function to map identifying values, known as keys , to their associated values . Thus, a hash table implements an associative array...

 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
Tree (data structure)
In computer science, a tree is a widely-used data structure that emulates a hierarchical tree structure with a set of linked nodes.Mathematically, it is an ordered directed tree, more specifically an arborescence: an acyclic connected graph where each node has zero or more children nodes and at...

.

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
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 coordinate actions across the system...

, makes unit testing far more difficult, 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.

External links

The source of this article is wikipedia, the free encyclopedia.  The text of this article is licensed under the GFDL.
 
x
OK