Frage

Die folgende Klasse:

class Pizza {

    Ingredients ingredients;
    Price price;

    public setIngredients(Ingredients ing) {
        if (ingredients != null) {
            throw new IllegalStateException();
        }
        ingredients = ing;
        return this;
    }

    public setPrice(Price p) {
        if (price != null) {
            throw new IllegalStateException();
        }
        price = p;
        return this;
    }

}

Könnte in einem Builder -Muster verwendet werden, und nachdem es gebaut wurde, ist es effektiv unveränderlich, weil jede Eigenschaft nur einmal festgelegt werden kann. Das ist:

Pizza pizza = new Pizza().setIngredients(something).setPrice(somethingelse);

Jedoch, Pizza ist nicht fadensicher: Es gibt keine Garantie dafür, dass Faden B die Zutaten sehen, die durch den Thread A eingestellt wurden. Es gibt einige Möglichkeiten, sie zu beheben:

  • Mitglieder machen final. Aber dann können Sie kein Builder -Muster verwenden.
  • Synchronisieren Sie den Zugriff auf Mitglieder. Aber das scheint wie Abfall, weil sie nur einmal geschrieben sind.
  • Mach sie volatile. Fühlt Abfall wie Synchronisation.
  • Verwenden AtomicReference.
  • Etc.?

Meine Frage ist, was ist der beste Weg, um dem JVM zu sagen, dass sich ein Klassenmitglied nicht ändert, nachdem eine Methode aufgerufen wurde? Sollte ich nur den Zugriff darauf synchronisieren und darauf vertrauen, dass die JVM das Schloss optimieren wird? Es fühlt sich nur verschwenderisch an, weil ich kennt dass das Mitglied sollte verhalten sich so wie es ist final Nachdem es gesetzt ist. Gibt es keine besseren Lösungen?

War es hilfreich?

Lösung

Builder -Muster bedeutet normalerweise, dass Builder ein separates Objekt ist. In diesem Fall können Sie Felder des zu erstellenden Objekts erstellen final, und initialisieren Sie sie im Konstruktor, das vom Builder -Objekt aufgerufen wurde:

Pizza pizza = 
    new PizzaBuilder()
        .setIngredients(something)
        .setPrice(somethingelse)
        .build(); 

Alternativ können Sie eine sichere Veröffentlichung der sicherstellen Pizza Objekt. Beachten Sie, dass sich sichere Veröffentlichungen an das Feld angewendet werden, das einen Verweis auf das veröffentlichte Objekt enthält, nicht auf die Felder dieses Objekts selbst. Zum Beispiel wenn pizza ist ein Feld eines Objekts, Sie können es schaffen volatile oder den Zugriff synchronisieren - es würde eine sichere Veröffentlichung von sicherstellen Pizza Objekt diesem Feld zugewiesen.

Andere Tipps

Wenn sich die Mitgliedswerte nie ändern sollen, wäre das bessere Muster eine Einführung von a Pizza Konstruktor, der als Parameter dauert Ingredients und Price, und haben überhaupt keine Settermethoden auf dem Objekt. Wirklich, es ist nicht nützlich, eine zu haben setSomething() Methode, die nach dem ersten Mal aufgerufen wird.

Überlegen Sie, wie das String Klasse funktioniert. Sobald Sie instanziiert haben a String Mit einem Text kann der Textwert nicht geändert werden. Der einzige Weg, um eine zu bekommen String Mit einem anderen Wert ist es, eine neue zu konstruieren. Es scheint, als ob Sie hier wollen.

Die Verwendung dieses Musters vermeidet auch das Synchronisationsproblem.

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