Ich habe einen Algorithmus, der eine Sammlung von Objekten erstellt. Diese Objekte können während der Erstellung geändert werden, da sie mit sehr wenig anfangen, aber dann an verschiedenen Stellen im Algorithmus mit Daten gefüllt werden.
Nach Abschluss des Algorithmus sollten die Objekte niemals geändert werden - sie werden jedoch von anderen Teilen der Software verwendet.
Wird es in diesen Szenarien als gute Praxis angesehen, zwei Versionen der Klasse zu haben, wie unten beschrieben?
- Das veränderbare wird dann durch den Algorithmus erzeugt
- Nach Abschluss des Algorithmus werden die Daten in unveränderbare Objekte kopiert, die zurückgegeben werden.
Antworten:
Sie können möglicherweise das Builder-Muster verwenden . Es wird ein separates Builder-Objekt verwendet, um die erforderlichen Daten zu erfassen. Wenn alle Daten erfasst sind, wird das eigentliche Objekt erstellt. Das erstellte Objekt kann unveränderlich sein.
quelle
Eine einfache Möglichkeit, dies zu erreichen, wäre eine Schnittstelle, über die man Eigenschaften lesen und nur Nur-Lese-Methoden aufrufen kann, und eine Klasse, die diese Schnittstelle implementiert, mit der Sie auch diese Klasse schreiben können.
Ihre Methode, die es erstellt, verarbeitet das erstere und gibt das letztere zurück, wobei nur eine schreibgeschützte Schnittstelle zur Interaktion bereitgestellt wird. Dies würde kein Kopieren erfordern, und Sie können das Verhalten, das Sie dem Anrufer zur Verfügung stellen möchten, im Gegensatz zum Ersteller auf einfache Weise optimieren.
Nehmen Sie dieses Beispiel:
Der einzige Nachteil dieses Ansatzes besteht darin, dass er einfach in die implementierende Klasse umgewandelt werden kann. Wenn es um Sicherheit geht, reicht es nicht aus, diesen Ansatz zu verwenden. Eine Problemumgehung besteht darin, dass Sie eine Fassadenklasse erstellen können, um die veränderbare Klasse zu umschließen, die einfach eine Schnittstelle darstellt, mit der der Aufrufer arbeitet und auf das interne Objekt keinen Zugriff hat.
Auf diese Weise hilft Ihnen nicht einmal das Casting. Beide können von derselben schreibgeschützten Schnittstelle abgeleitet werden. Durch das Konvertieren des zurückgegebenen Objekts erhalten Sie jedoch nur die Facade-Klasse, die unveränderlich ist, da sie den zugrunde liegenden Status der umgebrochenen veränderlichen Klasse nicht ändert.
Erwähnenswert ist, dass dies nicht dem typischen Trend folgt, in dem ein unveränderliches Objekt durch seinen Konstruktor ein für allemal konstruiert wird. Verständlicherweise müssen Sie sich möglicherweise mit vielen Parametern befassen, aber Sie sollten sich fragen, ob alle diese Parameter im Voraus definiert werden müssen oder ob einige später eingeführt werden können. In diesem Fall sollte ein einfacher Konstruktor mit nur erforderlichen Parametern verwendet werden. Mit anderen Worten, verwenden Sie dieses Muster nicht, wenn es ein anderes Problem in Ihrem Programm verdeckt.
quelle
Sie können die Builder - Muster verwenden , wie @JacquesB sagt, oder denken , alternativ , warum es eigentlich ist , dass diese Objekte von Ihnen haben bei der Erstellung sein wandelbar?
Mit anderen Worten, warum muss der Erstellungsprozess zeitlich verteilt werden, anstatt alle erforderlichen Werte in den Konstruktor zu übertragen und Instanzen auf einmal zu erstellen?
Denn der Builder könnte eine gute Lösung für das falsche Problem sein.
Wenn das Problem darin besteht, dass Sie einen Konstruktor haben, der etwa 10 Parameter lang ist, und Sie möchten ihn abmildern, indem Sie das Objekt nach und nach erstellen, könnte dies bedeuten, dass das Design durcheinander ist und diese 10 Werte " bagged "/ gruppiert in ein paar Objekte ... oder das Hauptobjekt in ein paar kleinere aufgeteilt ...
In diesem Fall - bleiben Sie bei der Unveränderlichkeit, verbessern Sie einfach das Design.
quelle