5 Stimmen

Ist es verwirrend, diese Klasse eine "Fabrik" zu nennen?

Mein Verständnis von einem Werk ist, dass sie die Instanziierung konkreter Klassen kapselt, die alle eine gemeinsame abstrakte Klasse oder Schnittstelle erben. Dadurch kann der Client von der Entscheidung, welche konkrete Klasse erstellt werden soll, entkoppelt werden, was wiederum bedeutet, dass Sie konkrete Klassen zu Ihrem Programm hinzufügen oder aus ihm entfernen können, ohne den Code des Clients ändern zu müssen. Möglicherweise müssen Sie die Fabrik ändern, aber die Fabrik ist "zweckgebunden" und hat eigentlich nur einen Grund, sich zu ändern - eine konkrete Klasse wurde hinzugefügt/entfernt.

Ich habe einige Klassen erstellt, die die Instanziierung von Objekten tatsächlich kapseln, aber aus einem anderen Grund: Die Objekte sind schwer zu instanziieren. Im Moment nenne ich diese Klassen "Fabriken", aber ich befürchte, dass das eine falsche Bezeichnung ist und andere Programmierer, die sich meinen Code ansehen, verwirren könnte. Meine "Factory"-Klassen entscheiden nicht, welche konkrete Klasse instanziiert werden soll, sondern sie garantieren, dass eine Reihe von Objekten in der richtigen Reihenfolge instanziiert wird und dass die richtigen Klassen an die richtigen Konstruktoren übergeben werden, wenn ich new() .

Zum Beispiel habe ich für ein MVVM-Projekt, an dem ich arbeite, eine Klasse geschrieben, um sicherzustellen, dass meine SetupView richtig instanziiert wird. Es sieht in etwa so aus:

public class SetupViewFactory
{
    public SetupView CreateView(DatabaseModel databaseModel, SettingsModel settingsModel, ViewUtilities viewUtilities)
    {
        var setupViewModel = new SetupViewModel(databaseModel, settingsModel, viewUtilities);
        var setupView = new SetupView();
        setupView.DataContext = setupViewModel;
        return setupView;
    }
}

Ist es verwirrend, dies eine "Fabrik" zu nennen? Sie entscheidet nicht zwischen mehreren möglichen konkreten Klassen, und ihr Rückgabetyp ist keine Schnittstelle oder ein abstrakter Typ, aber sie kapselt die Objektinstanziierung.

Wenn es keine "Fabrik" ist, was ist es dann?


bearbeiten

Einige Leute haben vorgeschlagen, dass dies tatsächlich das Builder-Muster ist.

Die Definition des Builder-Musters aus dofactory ist wie folgt:

Trennen Sie die Konstruktion eines komplexen Objekts von seiner Darstellung, so dass derselbe Konstruktionsprozess verschiedene Darstellungen erzeugen kann.

Auch das scheint ein wenig weit hergeholt zu sein. Was mich stört, sind die "unterschiedlichen Darstellungen". Mein Ziel ist es nicht, den Prozess der Erstellung einer Ansicht zu abstrahieren (nicht, dass das nicht ein lohnendes Ziel wäre). Ich versuche einfach, die Logik für die Erstellung einer bestimmten Ansicht an einem Ort zu platzieren, so dass ich bei einer Änderung der Bestandteile oder des Prozesses zur Erstellung dieser Ansicht nur diese eine Klasse ändern muss. Das Builder-Pattern scheint wirklich zu sagen: "Lass uns einen allgemeinen Prozess für die Erstellung von Views erstellen, dann kannst du denselben grundlegenden Prozess für jede View, die du erstellst, befolgen." Schön, aber das ist einfach nicht das, was ich hier tue.


Bearbeiten 2

Ich habe gerade ein interessantes Beispiel in einem Wikipedia-Artikel über Dependency Injection .

Unter "Manually Injected Dependency" enthält sie die folgende Klasse:

public class CarFactory {

    public static Car buildCar() {
        return new Car(new SimpleEngine());
    }

}

Dies ist fast genau die Verwendung, die ich habe (und, nein, ich habe den Wiki-Artikel nicht geschrieben :)).

Interessanterweise ist dies der Kommentar nach diesem Code:

Im obigen Code übernimmt das Werk die Verantwortung für den Zusammenbau des Fahrzeugs und baut den Motor in das Fahrzeug ein. Dadurch muss das Auto nicht mehr wissen, wie man einen Motor herstellt, allerdings muss die CarFactory nun über die Konstruktion des Motors Bescheid wissen. Man könnte eine EngineFactory erstellen, aber das schafft nur Abhängigkeiten zwischen den Fabriken. Das Problem bleibt also bestehen, wurde aber zumindest verschoben in Fabriken ou Bauherr Objekte. (meine Hervorhebung)

Das zeigt mir, dass ich zumindest nicht der Einzige bin, der daran gedacht hat, eine Klasse zu erstellen, die dabei hilft, Dinge in eine andere Klasse zu injizieren, und ich bin auch nicht der Einzige, der versucht hat, diese Klasse eine Fabrik zu nennen.

1voto

Jason Punyon Punkte 38137

Das erscheint mir ein wenig seltsam. Es ist keine abstrakte Fabrik, aber es passt auch nicht ganz in das Builder-Muster. Was für mich am meisten Sinn machen würde, ist, anstatt die SetupViewFactory mit der Methode CreateView zu haben, würde ich diese Methode in die SetupView-Klasse verschieben und sie statisch machen. Du hättest also...

public class SetupView
{
    public static SetupView CreateView(DatabaseModel databaseModel, SettingsModel settingsModel, ViewUtilities viewUtilities)
    {
        var setupViewModel = new SetupViewModel(databaseModel, settingsModel, viewUtilities);
        var setupView = new SetupView();
        setupView.DataContext = setupViewModel;
        return setupView;
    }
}

Jetzt haben Sie eine so genannte statische Fabrik oder eine Fabrikmethode. Sie können noch einen Schritt weiter gehen und die SetupView-Konstruktoren privatisieren, so dass die einzige Möglichkeit, eine Instanz von SetupView zu erhalten, darin besteht, die Fabrikmethode aufzurufen.

Als Antwort auf den Kommentar von OP:

Wenn es eine solche Notwendigkeit für die Trennung würde ich vermeiden, die SetupViewModel irgendwo in diesem Teil des Codes. Geben Sie stattdessen einfach das SetupViewModel ein, das Sie mit Ihrem SetupView verknüpfen möchten, und nicht die konstituierenden Eigenschaften, die Sie an den Konstruktor des SetupViewModel übergeben. So wird der Code...

public class SetupView
{
    public static SetupView CreateView(SetupViewModel model)
    {
        var setupView = new SetupView(); { DataContext = model };
        return setupView;
    }
}

1voto

Jeff Sternal Punkte 46528

Warum nicht zwei Klassen mit einfachen Konstruktoren?

 public class SetupViewModel {
      public SetupViewModel(DatabaseModel databaseModel, SettingsModel settingsModel, ViewUtilities viewUtilities) {
          this.DatabaseModel = databaseModel;
          this.SettingsModel = settingsModel;
          this.ViewUtilities = viewUtilities;
      }
 }

y

 public class SetupView {         
      public SetupView(SetupViewModel model) {              
          this.DataContext = model;
      }
 }

Auf diese Weise geben beide Klassen deutlich an, was sie für die Konstruktion benötigen.

0voto

T.E.D. Punkte 42630

Man könnte es einen "Zauberer" nennen.

0voto

Excalibur2000 Punkte 75

Ich würde eher Jason zustimmen. Für mich ist es eher ein Builder-Muster, aber wenn man SetupView in eine Schnittstelle verwandelt, wäre es eher ein Factory-Muster. Der Schlüssel zum Factory-Muster ist, dass das Factory-Muster die ganze Arbeit macht und entscheidet, was vom Funktionsaufruf zurückgegeben werden soll. Ich würde also denken, dass Sie einen Schalter haben müssen, der zwischen verschiedenen Optionen angesichts der Eingabeparameter auswählt.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X