Ich habe also eine Fabrik, die Objekte verschiedener Klassen erstellt. Die möglichen Klassen stammen alle von einem abstrakten Vorfahren. Die Factory verfügt über eine Konfigurationsdatei (JSON-Syntax) und entscheidet abhängig von der Konfiguration des Benutzers, welche Klasse erstellt werden soll.
Um dies zu erreichen, verwendet die Factory boost :: property_tree für das JSON-Parsing. Er geht durch den Baum und entscheidet, welches konkrete Objekt er erstellt.
Die Produktobjekte haben jedoch viele Felder (Attribute). Abhängig von der konkreten Klasse hat das Objekt ungefähr 5-10 Attribute, in Zukunft vielleicht sogar mehr.
Ich bin mir also nicht sicher, wie der Konstruktor der Objekte aussehen soll. Ich kann mir zwei Lösungen vorstellen:
1) Der Konstruktor des Produkts erwartet jedes Attribut als Parameter, sodass der Konstruktor mehr als 10 Parameter erhält. Dies ist hässlich und führt zu langen, unlesbaren Codezeilen. Der Vorteil ist jedoch, dass die Factory den JSON analysieren und den Konstruktor mit den richtigen Parametern aufrufen kann. Die Produktklasse muss nicht wissen, dass sie aufgrund der JSON-Konfiguration erstellt wurde. Es muss nicht wissen, dass es sich überhaupt um JSON oder Konfiguration handelt.
2) Der Konstruktor des Produkts erwartet nur ein Argument, das property_tree-Objekt. Dann kann es die benötigten Informationen analysieren. Wenn Informationen in der Konfiguration fehlen oder außerhalb der Grenzen liegen, kann jede Produktklasse ordnungsgemäß reagieren. Die Fabrik muss nicht wissen, welche Argumente von den verschiedenen Produkten benötigt werden. Das Werk muss auch nicht wissen, wie es bei falscher Konfiguration reagieren soll. Und die Konstruktorschnittstelle ist einheitlich und klein. Als Nachteil muss das Produkt jedoch die erforderlichen Informationen aus dem JSON extrahieren, damit es weiß, wie es aufgebaut ist.
Ich bevorzuge eher Lösung 2). Ich bin mir jedoch nicht sicher, ob dies ein gutes Fabrikmuster ist. Es fühlt sich irgendwie falsch an, das Produkt wissen zu lassen, dass es mit der JSON-Konfiguration erstellt wurde. Auf der anderen Seite können neue Produkte sehr einfach eingeführt werden.
Irgendwelche Meinungen dazu?
Antworten:
Ich würde Option 2 nicht ausführen, da Sie dann die Konstruktion Ihres Objekts für immer mit dem Parsen von Boost-Eigenschaftsbäumen verknüpft haben. Wenn Sie mit einer Klasse vertraut sind, die so viele Parameter benötigt, sollten Sie mit einem Konstruktor vertraut sein, der so viele Parameter benötigt, so ist das Leben!
Wenn Ihr Hauptanliegen die Lesbarkeit von Code ist, können Sie das Builder-Muster verwenden. Dies ist im Grunde die C ++ / Java-Notlösung, da keine benannten Argumente vorhanden sind. Am Ende haben Sie Dinge, die so aussehen:
Jetzt hat MyObject einen privaten Konstruktor, der in Builder :: build aufgerufen wird. Das Schöne ist, dass dies der einzige Ort ist, an dem Sie jemals einen Konstruktor mit 10 Parametern aufrufen müssen. Die Baumfactory der Boost-Eigenschaft verwendet den Builder. Wenn Sie anschließend ein MyObject direkt oder aus einer anderen Quelle erstellen möchten, durchlaufen Sie den Builder. Mit dem Builder können Sie jeden Parameter bei der Übergabe eindeutig benennen, damit er besser lesbar ist. Dies fügt natürlich etwas Boilerplate hinzu, sodass Sie entscheiden müssen, ob es sich lohnt, wenn Sie nur den chaotischen Konstruktor aufrufen oder einige Ihrer vorhandenen Parameter in Strukturen usw. zusammenfassen. Wirf einfach eine andere Option auf den Tisch.
https://en.wikipedia.org/wiki/Builder_pattern#C.2B.2B_Example
quelle
Verwenden Sie NICHT den zweiten Ansatz.
Dies ist definitiv nicht die Lösung und würde nur dazu führen, dass Klassen in Ihrer Geschäftslogik instanziiert werden, anstatt in dem Teil Ihrer App, in dem sich die Fabriken befinden.
Entweder:
Sofern es sich bei dem von Ihnen erstellten Objekt nicht um eine Klasse handelt, die für das Speichern von Daten verantwortlich ist, sollten Sie versuchen, den Code umzugestalten und die große Klasse in kleinere aufzuteilen.
quelle
new
oder Erstellen von Objekten in Ihrer Geschäftslogik vermeiden , ist das Design nicht sehr gut. Schauen Sie sich die Suche nicht Dinge von Miško Hevery sprechen , die in mehr Tiefe erklärt , warum Sie die Fabrik Ansatz angedeutet sowohl schlecht aus Tests und Lese Sicht. Außerdem scheint Ihre Klasse ein Datenobjekt zu sein, und für diese ist es im Allgemeinen in Ordnung, mehr Parameter als die reguläre Serviceklasse zu haben. Ich würde mich nicht allzu sehr darum kümmern.Option 2 ist fast richtig.
Eine verbesserte Option 2
Erstellen Sie eine "nach vorne gerichtete" Klasse, deren Aufgabe es ist, dieses JSON-Strukturobjekt zu nehmen, die Bits auszuwählen und die Factory-Konstruktoren aufzurufen. Es nimmt, was die Fabrik macht und gibt es dem Kunden.
Grundsätzlich sagt das "Frontend" zu den 2 Bobs: "Ich kümmere mich um die redigierten Kunden, damit die Ingenieure nicht müssen! Ich habe menschliche Fähigkeiten!" Armer Tom. Wenn er nur gesagt hätte "Ich entkopple den Kunden vom Bau. Dieses Ergebnis ist eine sehr zusammenhängende Fabrik"; er könnte seinen Job behalten haben.
Zu viele Argumente?
Nicht für die Client-Front-End-Kommunikation.
Frontend - Fabrik? Wenn nicht 10 Parameter, dann ist das Beste, was Sie tun können, das Auspacken zu verschieben, wenn nicht das ursprüngliche JSON-Ding, dann etwas DTO. Ist das besser, als den JSON an die Fabrik weiterzugeben? Gleicher Unterschied, sage ich.
Ich würde dringend in Betracht ziehen, einzelne Parameter zu übergeben. Halten Sie sich an das Ziel einer sauberen, zusammenhängenden Fabrik. Vermeiden Sie die Bedenken der @ DavidPacker-Antwort.
Milderung "zu vieler Argumente"
Fabrik- oder Klassenkonstrukteure
Gruppierung von Front-End-Argumenten
quelle