Ich habe über das Wochenende etwas Code geschrieben und wollte eine Factory als statische Methode in einer Basisklasse schreiben.
Meine Frage ist nur zu wissen, ob dies ein akzeptabler Ansatz ist.
Mein Gefühl, dass dies möglicherweise nicht der Fall ist, beruht auf der Tatsache, dass die Basisklasse Kenntnisse über die abgeleitete Klasse hat.
Trotzdem bin ich mir nicht sicher, wie ich auf einfachere Weise das gleiche Ergebnis erzielen kann. Eine ganze andere Fabrikklasse scheint (zumindest für mich) eine unnötige Komplexität zu sein (?)
Etwas wie:
class Animal
{
public static Animal CreateAnimal(string name)
{
switch(name)
{
case "Shark":
return new SeaAnimal();
break;
case "Dog":
return new LandAnimal();
break;
default:
throw new Exception("unknown animal");
}
}
}
class LandAnimal : Animal
{
}
class SeaAnimal : Animal
{
}
c#
class-design
Aaron Anodide
quelle
quelle
Antworten:
Nun, der Vorteil einer separaten Werksklasse ist, dass sie in Unit-Tests verspottet werden kann.
Wenn Sie dies jedoch nicht tun oder auf andere Weise polymorph machen möchten, ist eine statische Factory-Methode für die Klasse selbst in Ordnung.
quelle
Sie können Generics verwenden, um die switch-Anweisung zu umgehen und die nachfolgenden Implementierungen auch von der Basisklasse zu entkoppeln:
Verwendung:
oder
quelle
Im Extremfall könnte die Fabrik auch generisch sein.
Dann kann man jede Art von Objektfabrik erzeugen, die wiederum jede Art von Objekt erzeugen kann. Ich bin nicht sicher, ob das einfacher ist, es ist sicherlich allgemeiner.
Ich sehe nichts falsches an einer switch-Anweisung für eine kleine Factory-Implementierung. Sobald Sie sich mit einer großen Anzahl von Objekten oder möglichen unterschiedlichen Klassenhierarchien von Objekten befasst haben, ist ein allgemeinerer Ansatz meiner Meinung nach besser geeignet.
quelle
Schlechte Idee. Erstens verstößt es gegen das Open-Closed-Prinzip. Für jedes neue Tier müsstest du dich erneut mit deiner Basisklasse anlegen und du würdest sie möglicherweise zerstören. Die Abhängigkeiten würden in die falsche Richtung gehen.
Wenn Sie Tiere aus einer Konfiguration erstellen müssen, wäre ein Konstrukt wie dieses in Ordnung, obwohl die Verwendung von Reflektion, um den Typ zu erhalten, der dem Namen entspricht, und dessen Instanziierung unter Verwendung der erhaltenen Typinformationen eine bessere Option wäre.
Sie sollten jedoch trotzdem eine dedizierte Factory-Klasse erstellen, die nicht an die Tierklassenhierarchie gebunden ist, und statt eines Basistyps eine IAnimal-Schnittstelle zurückgeben. Dann wäre es sinnvoll, Sie hätten eine gewisse Entkopplung erreicht.
quelle
Diese Frage ist für mich aktuell - ich habe gestern fast genau solchen Code geschrieben. Ersetzen Sie einfach "Animal" durch das, was in meinem Projekt relevant ist, obwohl ich hier zur Diskussion bei "Animal" bleiben werde. Anstelle einer switch-Anweisung hatte ich eine etwas komplexere Folge von if-Anweisungen, bei denen mehr als nur ein Vergleich einer Variablen mit bestimmten festen Werten durchgeführt wurde. Aber das ist ein Detail. Eine statische Factory-Methode schien ein guter Weg zu sein, um Dinge zu entwerfen, da das Design aus der Umgestaltung früherer schneller und schmutziger Code-Unordnung hervorgegangen ist.
Ich habe diesen Entwurf abgelehnt, weil die Basisklasse Kenntnis von der abgeleiteten Klasse hatte. Wenn die Klassen LandAnimal und SeaAnimal klein, übersichtlich und einfach sind, können sie sich in derselben Quelldatei befinden. Aber ich habe große Probleme beim Lesen von Textdateien, die nicht den offiziellen Standards entsprechen. Ich möchte, dass meine LandAnimal-Klasse in einer eigenen Quelldatei gespeichert wird.
Dies führt zu einer Abhängigkeit von zirkulären Dateien - LandAnimal wird von Animal abgeleitet, Animal muss jedoch bereits wissen, dass LandAnimal, SeaAnimal und fünfzehn weitere Klassen existieren. Ich habe die Factory-Methode rausgezogen und in eine eigene Datei geschrieben (in meiner Hauptanwendung, nicht in meiner Animals-Bibliothek). Eine statische Factory-Methode zu haben schien nett und clever zu sein, aber ich erkannte, dass sie eigentlich kein Designproblem löste.
Ich habe keine Ahnung, wie das mit idiomatischem C # zusammenhängt, da ich oft die Sprache wechsle, ignoriere ich normalerweise Redewendungen und Konventionen, die für Sprachen und Entwicklerstapel außerhalb meiner üblichen Arbeit typisch sind. Wenn überhaupt, könnte mein C # "pythonisch" aussehen, wenn das sinnvoll ist. Ich bemühe mich um allgemeine Klarheit.
Ich weiß auch nicht, ob die Verwendung der statischen Factory-Methode bei kleinen, einfachen Klassen von Vorteil ist, die in der Zukunft wahrscheinlich nicht erweitert werden. In einigen Fällen kann es hilfreich sein, alle Klassen in einer Quelldatei zu haben.
quelle