Factory-Muster
Teil des Abschnitts Objektorientierte Programmierung der C#-Journey von Coddy. Lektion 53 von 70.
Das Factory pattern ist ein Erstellungsmuster, das die Objekterstellung an eine separate Methode oder Klasse delegiert. Anstatt new direkt in deinem Code zu verwenden, bittest du eine Factory, Objekte für dich zu erstellen. Dadurch wird die Erstellungslogik zentralisiert und dein Code wird flexibler.
Stell dir ein Szenario vor, in dem du verschiedene Arten von Dokumenten erstellen musst. Ohne eine Factory wird dein Code eng an bestimmte Klassen gekoppelt:
// Ohne Factory - verstreute Erstellungslogik
IDocument doc;
if (type == "pdf")
doc = new PdfDocument();
else if (type == "word")
doc = new WordDocument();Eine Factory kapselt diese Entscheidungsfindung an einer Stelle:
public interface IDocument
{
void Open();
}
public class PdfDocument : IDocument
{
public void Open() => Console.WriteLine("Opening PDF");
}
public class WordDocument : IDocument
{
public void Open() => Console.WriteLine("Opening Word");
}
public class DocumentFactory
{
public IDocument Create(string type)
{
return type switch
{
"pdf" => new PdfDocument(),
"word" => new WordDocument(),
_ => throw new ArgumentException("Unknown type")
};
}
}Nun fordert der Client-Code einfach an, was er benötigt, ohne die konkreten Klassen zu kennen:
var factory = new DocumentFactory();
IDocument doc = factory.Create("pdf");
doc.Open(); // PDF öffnenDas Factory-Muster ist besonders nützlich, wenn du später neue Typen hinzufügen musst. Das Hinzufügen eines SpreadsheetDocument erfordert Änderungen nur in der Factory und nicht überall dort, wo Dokumente erstellt werden. Diese Trennung macht deine Codebasis leichter zu warten und zu testen.
Aufgabe
EinfachErstellen wir ein Benachrichtigungssystem mithilfe des Factory-Musters. Anstatt verschiedene Benachrichtigungstypen direkt an verschiedenen Stellen in deinem Code zu erstellen, zentralisierst du die Erstellungslogik in einer Factory-Klasse, die anhand eines einfachen String-Bezeichners entscheidet, welche Benachrichtigung erstellt werden soll.
Du organisierst deinen Code auf drei Dateien verteilt:
Notification.cs: Definiere im NamespaceINotificationeinNotifications-Interface mit einer einzelnen MethodeSend(string message), die einen String zurückgibt. Erstelle anschließend drei Klassen, die dieses Interface implementieren:EmailNotification– gibt"Email: {message}"zurückSmsNotification– gibt"SMS: {message}"zurückPushNotification– gibt"Push: {message}"zurück
NotificationFactory.cs: Erstelle im selben Namespace eineNotificationFactory-Klasse mit einerCreate(string type)-Methode, die abhängig vom Typ-String das passendeINotificationzurückgibt:"email"gibt eineEmailNotificationzurück"sms"gibt eineSmsNotificationzurück"push"gibt einePushNotificationzurück
EmailNotificationzurück.Program.cs: Führe alles zusammen, indem du eine Factory-Instanz erstellst und sie verwendest, um Benachrichtigungen basierend auf der Eingabe zu erstellen. Die Factory übernimmt die gesamte Entscheidungslogik darüber, welche konkrete Klasse instanziiert werden soll.
Du erhältst zwei Eingaben:
- Den Benachrichtigungstyp (z. B.
sms) - Die zu sendende Nachricht (z. B.
Your order has shipped)
Verwende deine Factory, um den passenden Benachrichtigungstyp zu erstellen, rufe anschließend seine Send-Methode mit der Nachricht auf und gib das Ergebnis aus.
Wenn die Eingaben beispielsweise push und Meeting in 5 minutes lauten, sollte die Ausgabe wie folgt aussehen:
Push: Meeting in 5 minutesBeachte, dass dein Hauptcode niemals new EmailNotification() oder etwas Ähnliches verwendet – er fragt die Factory einfach nach dem, was er benötigt. Wenn du später eine SlackNotification hinzufügst, musst du nur die Factory aktualisieren und nicht jede Stelle, an der Benachrichtigungen erstellt werden!
Probier es selbst
using System;
using Notifications;
class Program
{
public static void Main(string[] args)
{
// Eingabe lesen
string type = Console.ReadLine();
string message = Console.ReadLine();
// TODO: Erstelle eine NotificationFactory-Instanz
// TODO: Verwende die Factory, um die passende Benachrichtigung zu erstellen
// TODO: Rufe die Send-Methode auf und gib das Ergebnis aus
}
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP
Externe DateienNamespaces & DirektivenEinführung in Klassen & ObjekteDas 'this'-SchlüsselwortMethoden und ParameterFelder vs. EigenschaftenKonstruktorenObjektinitialisiererWiederholung – Einfacher Taschenrechner4Vererbung
Grundlegende Vererbungs-(:)-SyntaxDas „base“-Schlüsselwort„virtual“- und „override“-SchlüsselwörterVersiegelte KlassenDie „object“-BasisklasseWiederholung – Mitarbeiterhierarchie7Erweiterte Funktionen
Überladen von OperatorenIndexer (this[])ToString()-ÜberschreibungErweiterungsmethodenRückblick – Benutzerdefinierte Liste10Entwurfsmuster Teil 1
Einführung in EntwurfsmusterThread-sicheres SingletonFactory-MusterObserver-Muster (Events)Strategy-Muster13Abschließende Herausforderungen
E-Learning-PlattformKomponente für SpielfigurenFahrzeugvermietungsdienst2Eigenschaften & statische Member
Automatisch implementierte EigenschaftenNur lesbare/schreibbare EigenschaftenStatische Felder & MethodenStatische KlassenMember mit Ausdruckskörpern5Polymorphie & Interfaces
Compile- vs. Laufzeit-PolymorphieInterface vs. abstrakte KlasseMehrere InterfacesExplizite InterfacesUpcasting & DowncastingWiederholung – Formenrechner3Klassenarchitektur
Instanz- vs. statische DatenSchlüsselwörter 'readonly' & 'const'Backing FieldsRückblick – Bankkontenverwaltung6Kapselung
ZugriffsmodifikatorenEigenschaften zur KapselungImplementierung der DatenkapselungMuster für UnveränderlichkeitRückblick – SchülerdatenÜbe selbstständig: Online-C#-Compiler