Assurer la visibilité de la mémoire avec le modèle constructeur / usine
-
28-10-2019 - |
Question
La classe suivante:
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;
}
}
pourrait être utilisé dans un modèle de constructeur, et après il a été construit, il est efficacement immuable , parce que chaque propriété peut être définie qu'une seule fois. C'est:
Pizza pizza = new Pizza().setIngredients(something).setPrice(somethingelse);
Cependant, Pizza
est pas sûre: il n'y a aucune garantie que le fil B voit les ingrédients qui ont été mis en elle par le fil A. Il existe des moyens pour y remédier:
-
final
membres. Mais vous ne pouvez pas utiliser un modèle de constructeur. - Synchronize l'accès aux membres. Mais cela semble comme les déchets, parce qu'ils sont écrits qu'une seule fois jamais.
- Faites-les
volatile
. Considère que les déchets, comme la synchronisation. - Utilisez
AtomicReference
. - Etc.
Ma question est, quelle est la meilleure façon de dire la machine virtuelle Java qu'un membre de la classe ne changera pas après une certaine méthode a été appelée? Dois-je simplement synchroniser l'accès à, et la confiance que la machine virtuelle Java optimisera loin la serrure? Il se sent juste déchets, parce que je sais que l'élément devrait se comporte comme elle est final
après sa série. Y a-t-il pas de meilleures solutions?
La solution
modèle Builder signifie généralement que le constructeur est un objet distinct. Dans ce cas, vous pouvez faire des champs de l'objet en cours de construction final
, et les initialiser dans le constructeur appelé par l'objet constructeur:
Pizza pizza =
new PizzaBuilder()
.setIngredients(something)
.setPrice(somethingelse)
.build();
Vous pouvez vous assurer en toute sécurité la publication de l'objet Pizza
. Notez que les idiomes de publication de sécurité sont appliquées au champ qui contient une référence à l'objet en cours de publication, de ne pas les champs de cet objet lui-même. Par exemple, si pizza
est un champ d'un objet, vous pouvez le rendre volatile
ou un accès synchronisent -. Il assurerait la publication en toute sécurité objet Pizza
attribué à ce champ
Autres conseils
Si les valeurs membres ne sont jamais destinées à changer, le meilleur modèle serait d'avoir un constructeur de Pizza
qui prend comme paramètres Ingredients
et Price
, et ne pas avoir des méthodes de réglage sur l'objet du tout. Vraiment il n'est pas utile d'avoir une méthode setSomething()
qui lance une exception après la première fois qu'il est appelé.
Considérons le fonctionnement de la classe String
. Une fois que vous avez instancié un String
avec un texte, la valeur de texte ne peut pas être modifié. La seule façon d'obtenir un String
avec une valeur différente est de construire une nouvelle. Il semble que c'est ce que vous voulez ici.
L'utilisation de ce modèle permet également d'éviter le problème de synchronisation.