Frage

Wenn Klassen modelliert, was ist die bevorzugte Methode zur Initialisierung:

  1. Constructors, oder
  2. Factory-Methoden

Und was die Überlegungen für die Verwendung einer von ihnen sein?

In bestimmten Situationen, ziehe ich eine Factory-Methode, die den Wert null zurück, wenn das Objekt nicht konstruiert werden kann. Dies macht den Code ordentlich. Ich kann einfach überprüfen, ob der zurückgegebene Wert vor der Einnahme alternative Aktion nicht Null ist, im Gegensatz zu einer Ausnahme von dem Konstruktor werfen. (Ich persönlich nicht Ausnahmen mag)

Sagen Sie, ich habe einen Konstruktor für eine Klasse, die einen ID-Wert erwartet. Der Konstruktor verwendet diesen Wert, die Klasse aus der Datenbank zu füllen. In dem Fall, dass ein Datensatz mit der angegebenen ID nicht existiert, wirft der Konstruktor ein RecordNotFoundException. In diesem Fall werde ich den Aufbau aller dieser Klassen innerhalb eines try..catch Block einzuschließen.

Im Gegensatz dazu kann ich auf diesen Klassen eine statische Factory-Methode habe, die null zurück, wenn der Datensatz nicht gefunden wird.

Welcher Ansatz ist besser, in diesem Fall Konstruktor oder Factory-Methode?

War es hilfreich?

Lösung

Von Seite 108 von Design Patterns: Elemente wiederverwendbarer objektorientierter Software von Gamma, Helm , Johnson und Vlissides.

Mit der Factory Method-Muster, wenn

  • eine Klasse kann die Klasse von Objekten nicht antizipieren es schaffen müssen
  • eine Klasse will ihre Unterklassen, die Objekte spezifizieren es schafft
  • Klassen Verantwortung an eine von mehreren Helfer-Subklassen delegieren, und Sie wollen das Wissen, welche Helfer Unterklasse der Delegat ist lokalisieren

Andere Tipps

Fragen Sie sich, was sie sind und warum wir sie tun. Sie sind beide dort Instanz eines Objekts zu erstellen.

ElementarySchool school = new ElementarySchool();
ElementarySchool school = SchoolFactory.Construct(); // new ElementarySchool() inside

Kein Unterschied so weit. Nun stell dir vor, dass wir verschiedene Schultypen haben, und wir wollen wechseln verwenden ElementarySchool zu Highschool (die von einem ElementarySchool abgeleitet ist oder implementiert die gleiche Schnittstelle iSchool als ElementarySchool). Die Codeänderung wäre:

HighSchool school = new HighSchool();
HighSchool school = SchoolFactory.Construct(); // new HighSchool() inside

Bei einer Schnittstelle hätten wir:

ISchool school = new HighSchool();
ISchool school = SchoolFactory.Construct(); // new HighSchool() inside

Nun, wenn Sie diesen Code haben an mehreren Stellen können Sie sehen, dass Methode Fabrik könnte ziemlich billig sein, weil, wenn Sie die Factory-Methode ändern Sie fertig sind (wenn wir das zweite Beispiel mit Schnittstellen verwenden).

Das ist der wesentliche Unterschied und Vorteil. Wenn Sie beginnen, mit einem komplexen Klassenhierarchien zu tun, und Sie möchten, um dynamisch eine Instanz einer Klasse aus einer solchen Hierarchie erstellen Sie den folgenden Code erhalten. Factory-Methoden könnten dann einen Parameter nehmen, die die Methode mitteilen, welche konkreten Beispiel zu instanziiert. Angenommen, Sie haben eine MyStudent Klasse haben, und Sie müssen entsprechende iSchool Objekt instanziiert, so dass Ihre Schüler ein Mitglied dieser Schule ist.

ISchool school = SchoolFactory.ConstructForStudent(myStudent);

Jetzt haben Sie einen Platz in Ihrer Anwendung, die Business-Logik enthält, welche iSchool Objekt bestimmt für verschiedene IStudent Objekte zu instanziiert.

So - für einfache Klassen (Wertobjekte, etc.) Konstruktor ist gut (Sie wollen nicht Ihre Anwendung overengineer), aber für komplexe Klassenhierarchien Factory-Methode ist eine bevorzugte Art und Weise.

Auf diese Weise folgen Sie dem erste Konstruktionsprinzip aus der Bande von vier Buch „Programm mit einer Schnittstelle, nicht eine Implementierung“.

Sie müssen lesen (wenn Sie Zugriff haben) Effective Java 2 Artikel. 1: Betrachten Sie statische Factory-Methoden anstelle von Konstrukteuren

Statische Fabrik Methoden Vorteile:

  1. Sie haben Namen.
  2. Sie werden nicht ein neues Objekt jedes Mal, wenn sie aufgerufen schaffen erforderlich ist.
  3. Sie können ein Objekt beliebigen Subtyp ihres Rückgabetypen zurück.
  4. Sie reduzieren Ausführlichkeit der parametrisierte Typ-Instanzen zu schaffen.

Statische Fabrik Methoden Nachteile:

  1. Wenn nur statische Factory-Methoden bereitstellt, Klassen ohne Konstrukteuren öffentlichen oder geschützten nicht subclassed werden.
  2. Sie sind nicht leicht zu unterscheiden von anderen statischen Methoden

Standardmäßig sollten Konstrukteure bevorzugt werden, da sie einfacher zu verstehen sind und zu schreiben. Wenn Sie jedoch speziell auf die Konstruktion Nettigkeiten ein Objekt aus seiner semantischen Bedeutung wie verstanden durch den Client-Code entkoppeln müssen, dann würden Sie besser mit Fabriken sein.

Der Unterschied zwischen Konstrukteuren und Fabriken ist analog zu, sagen wir, eine Variable und einen Zeiger auf eine Variable. Es gibt einen anderen Dereferenzierungsebene, was ein Nachteil ist; aber es gibt einen anderen Grad an Flexibilität zu, was ein Vorteil ist. Während also eine Wahl, würden Sie gut beraten, diese Kosten im Vergleich zu Nutzen-Analyse zu tun.

Ein zitieren von "Effective Java", 2. Aufl Punkt. 1: Betrachten Sie statische Factory-Methoden anstelle von Konstrukteuren, p. 5:

"Beachten Sie, dass eine statische Factory-Methode ist nicht das gleiche wie die Factory Method Muster von Design Patterns [Gamma95, p. 107]. Die statische Factory-Methode beschrieben in Dieser Artikel hat keine direkte Entsprechung in Design Patterns. "

nur eine Fabrik verwenden, wenn Sie zusätzliche Kontrolle mit Objekterstellung benötigen, in einer Weise, die nicht mit Konstrukteuren getan werden könnte.

Fabriken haben die Möglichkeit, Caching zum Beispiel.

Eine weitere Möglichkeit, Fabriken zu verwenden, ist in einem Szenario, in dem Sie nicht wissen, welche Art Sie bauen wollen. Oft sehen Sie diese Art der Nutzung in der Plugin-Fabrik-Szenarien, in denen jedes Plugin von einer Basisklasse ableiten müssen oder irgendeine Art von Schnittstelle implementieren. Die Fabrik erzeugt Instanzen von Klassen, die von der Basisklasse ableiten, oder dass der Schnittstelle implementieren.

Ein konkretes Beispiel aus einem CAD / CAM-Anwendung.

wäre ein Schneidweg durch die Verwendung eines Konstruktor vorgenommen werden. Es ist eine Reihe von Linien und Bögen einen Pfad definieren, zu schneiden. Während die Serie von Linien und Bögen verschieden sein können und verschiedene Koordinaten haben sie, indem man eine Liste in einen Konstruktor leicht zu handhaben.

Eine Form würde wäre gemacht werden, eine Fabrik unter Verwendung. Denn während es eine Form Klasse ist, würde jede Form Setup unterschiedlich sein, je nachdem, welche Art von Form ist. Wir wissen nicht, welche Form wir werden initialisiert werden, bis der Benutzer eine Auswahl trifft.

Zusätzlich zu "Effective Java" (wie in einer anderen Antwort erwähnt), ein weiteres klassisches Buch auch schlägt vor:

  

Bevorzugen statische Factory-Methoden (mit Namen, die die Argumente beschreiben) zu ladenen Konstruktoren.

Eg. nicht schreiben

Complex complex = new Complex(23.0);

, sondern schreibt

Complex complex = Complex.fromRealNumber(23.0);

Das Buch geht so weit zu behaupten, die Complex(float) Konstruktor privat machen, um den Benutzer zu zwingen, die statische Factory-Methode aufrufen.

  

Sagen Sie, ich habe einen Konstruktor für eine Klasse, die einen ID-Wert erwartet. Der Konstruktor verwendet diesen Wert, die Klasse aus der Datenbank zu füllen.

Dieser Prozess auf jeden Fall außerhalb eines Konstruktor sein sollte.

  1. Constructor sollte nicht Datenbank zugreifen zu können.

  2. Die Aufgabe und der Grund für einen Konstruktor ist Datenelemente initialisieren und etablieren Klasseninvariante Werten in Konstruktor übergeben.

  3. Für alles andere ein besserer Ansatz ist die Verwendung statische Factory-Methode oder in komplexeren Fällen eine separate Fabrik oder builder Klasse .

Einige Konstruktor Richtlinien von Microsoft :

  

Sie minimale Arbeit im Konstruktor. Konstrukteurs sollte nicht viel Arbeit anders als die Konstruktorparameter zu erfassen. Die Kosten für jede andere Verarbeitung sollte, bis sie benötigt verzögert werden.

Und

  

Betrachten wir eine statische Factory-Methode anstelle eines Konstruktor, wenn die Semantik der gewünschten Operation, nicht direkt auf den Bau einer neuen Instanz.

Manchmal muss man einige Werte / Bedingungen überprüfen / berechnen, während ein Objekt zu schaffen. Und wenn es eine Ausnahme auslösen kann - constructro ist sehr schlecht. Sie müssen also so etwas wie dies tun:

var value = new Instance(1, 2).init()
public function init() {
    try {
        doSome()
    }
    catch (e) {
        soAnotherSome()
    }
}

Wenn alle weiteren Berechnungen in init sind (). Aber nur Sie als Entwickler wirklich weiß über diese init (). Und natürlich, nach Monaten vergessen Sie nur darüber. Aber wenn Sie eine Fabrik haben - nur tut alles, was Sie in einem Verfahren müssen mit verstecken diese init () aus dem direkten Aufruf - so keine Probleme. Mit diesem Ansatz ist, keine Probleme mit dem Sturz auf der Schaffung und Speicher undicht.

Jemand sagte Sie Caching. Das ist gut. Aber Sie müssen auch über Flyweight-Muster erinnern, das ist schön mit der Fabrik zu nutzen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top