Simple Factory

Einführung

„Eine factory (Fabrik) ist ein Objekt um andere Objekte zu erstellen.“

Dieser Satz sagt im wesentlichen alles über das Simple Factory Pattern aus. Anstatt ein Objekt direkt über den Konstruktor zu instanzieren, wird eine spezielle Methode, eine Factory, für diesen Zweck verwendet. Meist findet das Simple Factory Pattern kaum Bedeutung und wird häufig als ein Teil, oder als Grundlage, von komplexeren Pattern verwendet. Beispiele dafür sind Object Libraries oder das Abstract Factory Pattern. Teilweise werden Simple Factories auch nicht als Pattern angesehen sondern eher als eine Grundlage der objektorientierten Programmierung.

Als Factory wird meist eine einzelne Methode bezeichnet, die ein bereits instanziertes Objekt zurückgibt.
Ein simples Beispiel:

C#

        static void Main(string[] args)
        {
            var kittyCat = Animal.CreateCat();

            Console.WriteLine($"My cat is {kittyCat.color} and his name is {kittyCat.name}");
            Console.ReadLine();
        }

        class Animal
        {
            public string name { get; set; }
            public string color { get; set; }

            public static Animal CreateCat()
            {
                var cat = new Animal
                {
                    name = "Kitty",
                    color = "black"
                };
                
                return cat;
            }
        }

JAVA

public class TestClass {

	public static void main(String[] args){
		animal kittyCat = Animal.CreateCat();
		
		System.out.println("My cat is " + kittyCat.getColor() + 
			" and his name is " + kittyCat.getName());
	}
}

public class Animal {
	private String name;
	private String color;
	
	public String getName() { return name; }
	public void setName(String name) { this.name = name; }
	
	public String getColor() { return color; }
	public void setColor(String color) { this.color = color; }
	
	public static Animal CreateCat()
	{
		Animal cat = new Animal();	
		cat.name = "Kitty";
		cat.color = "black";
		
		return cat;
	}
}



Ausgabe:
My cat is black and his name is Kitty

Die Methode CreateCat() der Klasse Animal dient hier als Factory um ein Animal-Objekt zu erstellen und dessen Eigenschaften zu initialisieren. In der Main()-Methode wird durch den Aufruf der Factory eine komplett fertige Katze erzeugt und deren Namen ausgegeben.

Encapsulation

Factories können, dem Grundsatz der Encapsulation (Datenkapselung), sehr einfach in eine seperate Klasse ausgelagert werden. Zusätzlich zur Kapselung wurde noch eine zweite Factory angelegt, die einen Hund erstellt:

C#

        static void Main(string[] args)
        {
            var kittyCat = AnimalFactories.CreateCat();
            var DoggyDog = AnimalFactories.CreateDog();

            Console.WriteLine($"My cat is {kittyCat.color} and his name is {kittyCat.name}");
            Console.WriteLine($"My dog is {DoggyDog.color} and his name is {DoggyDog.name}");
            Console.ReadLine();
        }

        class Animal
        {
            public string name { get; set; }
            public string color { get; set; }
        }

        class AnimalFactories
        {
            public static Animal CreateCat()
            {
                var cat = new Animal
                {
                    name = "Kitty",
                    color = "black"
                };

                return cat;
            }

            public static Animal CreateDog()
            {
                var dog = new Animal
                {
                    name = "Bingo",
                    color = "white"
                };

                return dog;
            }
        }

JAVA

public class TestClass {

	public static void main(String[] args){
		Animal kittyCat = AnimalFactories.CreateCat();
		Animal doggyDog = AnimalFactories.CreateDog();
		
		System.out.println("My cat is " + kittyCat.getColor() + 
				" and his name is " + kittyCat.getName());
		System.out.println("My dog is " + doggyDog.getColor() + 
				" and his name is " + doggyDog.getName());		
	}
}

public class Animal {
	private String name;
	private String color;
	
	public String getName() { return name; }
	public void setName(String name) { this.name = name; }
	
	public String getColor() { return color; }
	public void setColor(String color) { this.color = color; }
}

public class AnimalFactories {
	public static Animal CreateCat()
	{
		Animal cat = new Animal();	
		cat.setName("Kitty");
		cat.setColor("black");
		
		return cat;
	}	
	
	public static Animal CreateDog()
	{
		Animal cat = new Animal();	
		cat.setName("Bingo");
		cat.setColor("white");
		
		return cat;
	}		
}

Ausgabe:

My cat is black and his name is Kitty
My dog is white and his name is Bingo

Durch das Encapsulating der Factories ist die Klasse Animal komplett von den Factories getrennt geworden.

Polymorphismus

Ein weiterer guter Einsatzort für Factories ist Polymorphismus. Im folgenden ein Beispiel mit Subtyping:

C#

        static void Main(string[] args)
        {
            Animal myAnimal;

            myAnimal = AnimalFactories.CreateAnimal("cat");
            myAnimal.MakeNoise();

            myAnimal = AnimalFactories.CreateAnimal("dog");
            myAnimal.MakeNoise();

            Console.ReadLine();
        }

        abstract class Animal
        {
            public abstract void MakeNoise();
        }

       class Cat : Animal
        {
            public override void MakeNoise()
            {
                Console.WriteLine("MEOW!");
            }
        }

        class Dog : Animal
        {
            public override void MakeNoise()
            {
                Console.WriteLine("BARK!");
            }
        }

        class AnimalFactories
        {
            public static Animal CreateAnimal(string animalType)
            {
                switch(animalType)
                {
                    case "cat":
                        return new Cat();
                    case "dog":
                        return new Dog();
                    default:
                        return null;                
                }
            }
        }

JAVA

public class TestClass {

	public static void main(String[] args){
		Animal myAnimal;
		
		myAnimal = AnimalFactories.CreateAnimal("cat");
		myAnimal.MakeNoise();
		
		myAnimal = AnimalFactories.CreateAnimal("dog");
		myAnimal.MakeNoise();		
	}
}

abstract class Animal {
	public abstract void MakeNoise();
}

public class Cat extends Animal {
	@Override
	public void MakeNoise() {
		System.out.println("MEOW!");
	}
}

public class Dog extends Animal {
	@Override
	public void MakeNoise() {
		System.out.println("BARK!");
	}
}

public class AnimalFactories {
	public static Animal CreateAnimal(String animalType)
	{
		switch(animalType)
		{
			case "cat":
				return (Animal) new Cat();
			case "dog":
				return (Animal) new Dog();
			default:
				return null;
		}
	}		
}

Ausgabe:

MEOW!
BARK!

Die Factory-Klasse wurde dahingehend geändert, dass jetzt nur noch eine Methode zum Erstellen von Hund und Katz verwendet wird. Über einen Parameter wird festgelegt, welches Tier erstellt werden soll. Die Klassen Dog und Cat werden jeweils von der Animal-Klasse abgeleitet und überschreiben die Methode MakeNoise(). So erfolgt, je nach Parameterübergabe an die Factory, eine andere Ausgabe.

Abschließende Worte

Zum Abschluss kann gesagt werden, das Factories meist dann eingesetzt werden, wenn die Konstruktion eines Objektes komplexer wird oder wenn sie Teil eines weiteren Design Patterns sind. In den Beispielen ist das natürlich nicht der Fall, sie sollen mehr zum allgemeinen Verständnis beitragen.

Leave a Reply

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind markiert *

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>