Über das Fabrik-Methode Muster Teil 2

So…da hat es doch etwas länger gedauert, den letzten Artikel fortzusetzen. Was war also beim letzten Mal noch das Problem? Der Code wurde zwar an eine Stelle verschoben, an der er sich gut ändern lässt, allerdings sind da immer noch diese komischen, fehlerträchtigen String-Parameter. Des Weiteren ist das noch nicht so ganz flexibel. Was kann man also verändern? Statt nur eine Fabrik-Methode zu definieren, kann man pro Event eine Fabrik-Klasse erstellen, die sich einzig und allein um diese Event-Erstellung kümmert. Das ist zwar ein wenig aufwändiger, aber die Erstellung von Objekten ist gekapselt. Das ist doch schon mal was wert. Hier der (mal wieder nicht ganz perfekte) Code. Natürlich ist dieser Code jetzt wirklich sehr einfach, aber ich wollte allen unnötigen Ballast abwerfen (für eine wirklich realistische Implementierung reicht wohl auch der Platz nicht aus).

using System;
using System.Collections.Generic;

public interface IEvent
{
    void StartEvent();
    void FinishEvent();
    void ChangeEventDetails();
}

class Event:IEvent
{
    public void StartEvent()
    {
        Console.WriteLine("Starte Event");
    }

    public void FinishEvent()
    {
        Console.WriteLine("Beende Event");
    }

    public void ChangeEventDetails()
    {
        Console.WriteLine("Aendere Eventdetails");
    }
}

class ModernEvent : IEvent
{
    public void StartEvent()
    {
        Console.WriteLine("Starte ModernEvent");
    }

    public void FinishEvent()
    {
        Console.WriteLine("Beende ModernEvent");
    }

    public void ChangeEventDetails()
    {
        Console.WriteLine("Aendere ModernEventdetails");
    }
}

class OldFashionedEvent : IEvent
{
    public void StartEvent()
    {
        Console.WriteLine("Starte OldFashionedEvent");
    }

    public void FinishEvent()
    {
        Console.WriteLine("Beende OldFashionedEvent");
    }

    public void ChangeEventDetails()
    {
        Console.WriteLine("Aendere OldFashionedEventdetails");
    }
}

interface IEventFactory
{
    IEvent CreateEvent();
}

public class EventFactory:IEventFactory
{
    public IEvent CreateEvent()
    {
        return new Event();
    }
}

public class ModernEventFactory : IEventFactory
{
    public IEvent CreateEvent()
    {
        return new ModernEvent();
    }
}

public class OldFashionedEventFactory : IEventFactory
{
    public IEvent CreateEvent()
    {
        return new OldFashionedEvent();
    }
}

class EventManager
{
    static void Main(string[] args)
    {
        IEventFactory modernFactory = new ModernEventFactory();
        IEventFactory normalFactory = new EventFactory();
        IEventFactory oldfashionedFactory = new OldFashionedEventFactory();

        var eventList = new List<IEvent>
                            {
                                modernFactory.CreateEvent(),
                                normalFactory.CreateEvent(),
                                oldfashionedFactory.CreateEvent()
                            };

        foreach (var ievent in eventList)
        {
            ievent.StartEvent();
            ievent.FinishEvent();
            ievent.ChangeEventDetails();
        }

        Console.Read();
    }
}

Noch kurz zum Code: Es gibt jetzt ein Event-Interface, das den Kontrakt für die Eventklassen bildet. Dazu gibt es ein EventFactory-Interface, welches nur erzwingt, dass Implementierungen davon die CreateEvent()-Methode definieren müssen. In der Main-Methode sieht man sehr schön, wie man nun gegen Interfaces programmiert. Der Client weiß nur in geringem Maße, welche Factory er nutzt. Hier gibt es also noch eine Abhängigkeit zu beklagen.

Das ist es also, das Fabrikmethode-Muster, so wie ich es momentan verstanden habe. Es gibt sicher andere (womöglich auch bessere) Varianten, für den Einstieg reicht es aber vorerst so aus. Natürlich muss man hierbei Bedenken, dass man zwar mit diesem Muster sehr gut Kapselung betreiben kann, sich allerdings auch zusätzliche Komplexität dabei einfängt. Alles hat eben seine Vor – und Nachteile.