Factory method

Factory method – Definition

Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.

Gang of four (Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides)

Factory method – Struktur

Factory method – Pseudocode

// Beschreibt ein beliebiges Objekt, welches dynamisch und zur Laufzeit
// erzeugt werden soll.
interface Product

// Für jedes Produkt müssen mehrere konkrete Klassen definiert werden, welche
// anschließend in der Fabrik erstellt werden.
class ConcreteProductA implements Product
class ConcreteProductB implements Product

// Die Produkte sollen im besten Fall nur mithilfe der Fabrik erstellt werden.
class ProductFactory
	// Abhängig davon was angefragt wird, werden verschiedene Produkte
	// erzeugt. Anschließend bekommt man eine implementierung für genau
	// diese Anfrage
	method create(which) : Product
		if which is A
			return new ConcreteProductA()
		if which is B
			return new ConcreteProductB()

program Client
	// innerhalb des Clients, muss nur noch die Fabrik und
	// mit der Create-Methode das passende Objekt erzeugt werden
	var factory = new ProductFactory()
	Product a = factory.create(A);
	Product c = factory.create(B);

Factory method – C# Implementierung

In diesem Beispiel wurde der Aufbau einer Verbindung mit einer Datenquelle über ein Factory Pattern gelöst.

Den kompletten Quellcode (inkl. UnitTests) gibt es dazu auf github.

public interface IFactory<out TProduct>
{
	TProduct Create(string variation);
}

public interface IDataConnection
{
	void Connect();
}

class OdbcDataConnection : IDataConnection
{
	public void Connect()
		=> Console.WriteLine("Connecting to ODBC");
}

class MysqlDataConnection : IDataConnection
{
	public void Connect()
		=> Console.WriteLine("Connecting to MySQL");
}

class SqliteDataConnection : IDataConnection
{
	public void Connect()
		=> Console.WriteLine("Connecting to SQLite");
}

class InMemoryDataConnection : IDataConnection
{
	public void Connect()
		=> Console.WriteLine("Use only memory");
}

class JsonDataConnection : IDataConnection
{
	public void Connect()
		=> Console.WriteLine("Put everything into JSONs");
}

public class ConnectionFactory : IFactory<IDataConnection>
{
	public IDataConnection Create(string driver)
	{
		switch (driver)
		{
			case "odbc":
				return new OdbcDataConnection();
			case "mysql":
				return new MysqlDataConnection();
			case "sqlite":
				return new SqliteDataConnection();
			case "json":
				return new JsonDataConnection();
			case "memory":
			case "temp":
			case "mock":
				return new InMemoryDataConnection();
		}

		throw new UnknownConnectionDriverException("Driver not defined: " + driver);
	}
}