Muster: Multiton

Aus Wikibooks

Multiton[Bearbeiten]

Das Multiton ist sozusagen eine Erweiterung des Einzelstücks (auch Singletons), indem es nicht ein einziges Objekt, sondern eine Reihe von Objekten erzeugt, auf die mit einem eindeutigen Schlüssel zugegriffen werden kann.

Zweck[Bearbeiten]

Mit diesem Erzeugungsmuster können eine Anzahl von zusammenhängende Objekte so erzeugt werden, dass für jedes dieser Objekte wie beim Einzelstück sichergestellt ist, dass höchstens eins existiert.

UML[Bearbeiten]

Anwendungsfälle[Bearbeiten]

Das Multiton ist eine flexiblere Form eines Registrys - einer simplen Datensammlung von Objekten. Manche Entwurfsbücher sehen das Multiton als eine Erweiterung des Singleton und erwähnen es nicht als eigenständiges Muster.

Vorteile[Bearbeiten]

  • Sicherheit, dass für die eindeutig erreichbare Objekte nur eine Instanz vorhanden ist.
    • Speicher wird dadurch eingespart
    • Es wird immer auf ein und dieselbe Instanz zugegriffen (keine Daten-Duplikation)

Nachteile[Bearbeiten]

So wie es beim Einzelstück auch der Fall ist, wird mit einem Multiton

  • der Modul- oder Unit-Test erschwert, weil es einen globalen Zustand in die Anwendung einfügt
  • Parallelisierungen erschwert
  • Bei Sprachen mit Freispeichersammlung kann es durch Multiton zu Speicherlecks kommen.

Beispiele[Bearbeiten]

Ein Beispiel aus der Wikipedia folgt:

C#[Bearbeiten]

public enum EFamily
{
	ANNA,
	SIMON,
	SUSANNA,
	UWE,
}

public class Family
{
	private static Dictionary<EFamily, Family> instances = new Dictionary<EFamily, Family>();
	private String name;

	public String Name {
		get
		{
			return name;
		}
		private set
		{
			name = value;
		}
	}

	private Family() { }

	public Family(string name)
	{
		Name = name;
	}

	public static Family getInstance(EFamily key)
	{
		Family instance = null;

		try
		{
			instance = instances[key];
		}
		catch (Exception)
		{
			instance = new Family(GetName(key));

			instances.Add(key, instance);
		}
		return instance;
	}

	public static String GetName(EFamily key)
	{
		String name = key.ToString().ToLower();

		name = name[0].ToString().ToUpper() + name.Substring(1);

		return name;
	}

	public void WhoAmI()
	{
		Console.WriteLine("I am " + Name + '.');
	}
}

class AllDesignPatterns
{
	static void Main(string[] arguments)
	{
		Family father = Family.getInstance(EFamily.UWE);

		father.WhoAmI();
		Family mother = Family.getInstance(EFamily.ANNA);

		mother.WhoAmI();
		IsSame(father, mother);
		Family daughter = Family.getInstance(EFamily.SUSANNA);

		daughter.WhoAmI();
		IsSame(daughter, mother);
		Family son = Family.getInstance(EFamily.SIMON);

		son.WhoAmI();
		IsSame(father, son);
		Family member = Family.getInstance(EFamily.SUSANNA);

		member.WhoAmI();
		IsSame(daughter, member);
	}

	private static void IsSame(Family first, Family second)
	{
		if (first != null && second != null)
		{
			Console.Write(first.Name + " is");

			Console.Write(!first.Equals(second) ? " not" : "");

			Console.WriteLine(" the same person as " + second.Name + '.');
		}
	}
}

returns the following:

Susanna is the same person as Susanna.
I am Uwe.
I am Anna.
Uwe is not the same person as Anna.
I am Susanna.
Susanna is not the same person as Anna.
I am Simon.
Uwe is not the same person as Simon.
I am Susanna.
Susanna is the same person as Susanna.

Java[Bearbeiten]

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

    }

Implementation[Bearbeiten]

Für die Umsetzung des Multitons wird meist eine Hashtabelle o.Ä. verwendet. Dadurch ist es möglich, mit einem Schlüssel das jeweilige Objekt zu erreichen. Gibt es das Objekt noch nicht, wird null zurückgeliefert. Beim Schreiben wird das bestehende Objekt überschrieben oder neu angelegt - je nachdem, ob es schon existierte oder nicht.

Verwandte Muster[Bearbeiten]

Das Einzelstück (oder Singleton) ist die einfachste Form ohne Schlüssel, wo nur genau ein Objekt verwaltet wird.