J'ai deux classes immuables: Utilisateur strong> et Ministère Strong>, ils sont connectés à l'aide d'une association bidirectionnelle - code: p> class User {
private final Department department;
private final String name;
public User(Department department, String name) {
this.department = department;
this.name = name;
}
}
class Department {
private final List<User> users;
private final String name;
public Department(List<User> users, String name) {
this.users = new ArrayList<>(users);
this.name = name;
}
}
6 Réponses :
Département instancier avec la liste vide des utilisateurs. Ensuite, utilisez le service pour instantiier l'utilisateur et ajouter l'instance utilisateur à la liste des utilisateurs du département. P>
Dans ce cas, département code> S est toujours mutable i> :-(
Je ressens en vous cas de cas, vous pouvez modifier légèrement votre conception et utiliser spécial en général, ce n'est pas vraiment une bonne idée d'utiliser des objets référence avant que son constructeur se termine; Mais dans ce cas particulier, il semble sûr. p> usersBuilder code>, c'est-à-dire
Une approche est de modifier légèrement ce que vous comprenez immuable em> à signifier. Dans la conception orientée objet, il est conventionnel de distinguer entre les les attributs em> d'un objet et de ses associations em>. Les objets associés sont des entités différentes auxquelles l'objet a des références. Si vous détendez la définition de immuable em> pour signifier que les attributs em> de l'objet ne changent pas, mais permettent aux associations de changer, vous évitez ce type de problème. p>
Dans votre cas, utilisateur code> et
département des objets code> serait associé les uns aux autres, et chacun aurait un attribut code> nom p >
Vous pouvez produire des services immuables et des utilisateurs avec un constructeur supplémentaire sur le département. Du code des questions, il est déduit que
Étant donné que les utilisateurs ne sont vraiment que des chaînes associées à un département, un département peut être construit avec une liste Note: Que @andreemoniy a déclaré à propos de laisser Voici à quoi cela ressemblerait, dans Java 8: P>
Liste
ceci code> échappe à un Le constructeur ne doit pas être utilisé, mais il est en sécurité dans ce cas, car il ne s'agit que d'un constructeur d'instance utilisateur où cette instance utilisateur n'est pas accessible avant que le constructeur de département ne revienne. p>
public final class User {
private final Department department;
private final String name;
public User(Department department, String name) {
this.department = department;
this.name = name;
}
public Department getDepartment() {
return department;
}
public String getName() {
return name;
}
}
public final class Department {
private final List<User> users;
private final String name;
///Reversed argument list to avoid collision after erasure
public Department(String name, List<String> users) {
this.users = Collections.unmodifiableList(users.stream()
.map((s) -> new User(this,s)).collect(Collectors.toList()));
this.name = name;
}
public Department(List<User> users, String name) {
this.users = Collections.unmodifiableList(users);
this.name = name;
}
public List<User> getUsers() {
return users;
}
public String getName() {
return name;
}
}
Je pense que c'est une question de modélisation également. Ceci est correct de penser qu'un utilisateur a un département et un département ont des utilisateurs, mais la question est de la profondeur que vous pouvez regarder dans les données de l'utilisateur et du département?
Cela a-t-il un sens à moins que vous accédez conceptuellement d'accéder à User.Department.user [2] .name? Qu'en est-il du département.User [10] .Addresses [1] .street? P>
Je ne pense vraiment pas sur la plupart des scénarios. C'est une question de domaine d'information. Vous avez des bondaires tout en accédant à des données et que cela peut également être exprimé d'une manière d'une manière ou d'une autre dans vos modèles. P>
Si la modélisation de l'objet genre représente le monde réel, c'est bon de penser que lorsque vous allez dans un département, vous verrez des dizaines Des personnes travaillant là-bas et tout de probabilité que tout ce que vous pourrez savoir à leur sujet est le comptage et les noms peut-être. Donc, quelles tranches de données vous devriez pouvoir voir de votre objet? P>
Mon approche pour cela est: p> Je ne pense pas que je ne pense pas D Besoin de montrer comment les constructeurs fonctionnent depuis si vous avez remarqué que ce scénario, la nature bidirectionnelle de la relation n'est jamais là. Ainsi, lorsque vous construisez une personne, tout ce dont vous avez besoin est le MinistèreInfo (département Aucun employé non requis) et la même chose est valable lorsque vous construisez un département, lorsque tout ce que vous avez besoin d'avoir est le personnage des employés du département. P> < P> C'est ma façon de penser que ce problème conceptuellement. Des commentaires? P> p>
Merci pour la réponse, j'ai une réponse ajoutée avec une autre solution, semblable à votre idée, qu'en pensez-vous de cela?
C'est à peu près beaucoup, sinon je ne pense pas que ce soit une vraie bonne chose d'avoir une sorte d'entité appelée des département des ministères, mais cela fonctionne sûrement bien. Mon moyen de s'attaquer à ce que c'est la même chose, mais je préférais attraper les informations de base dans une * entité info
Ma solution consiste à: diviser l'une des classes immuables en deux classes: une classe avec les attributs et une classe avec l'association bidirectionnelle: afin de créer un nouvel utilisateur et un instance de service que vous devez: p>
Si vous voulez vraiment i> immuable
département code> Vous devez utiliser quelque chose comme
users = collections.unmodifiablelist (utilisateurs) code>. Mais vous aurez perdu la capacité d'ajouter des utilisateurs après cela et votre tâche devient impossible :)
@Andremoniy qui ne fera pas la classe immuable, puisque l'appelant a toujours une référence à la liste mutable enveloppée dans une liste non modifiable.
Vous posez des questions sur les principes de conception. Mais considérez ceci: si la classe de département devrait-elle vraiment être immuable? N'est-il pas mieux adapté comme une classe mutable qui pourrait ajouter et / ou supprimer des utilisateurs? Une fois cette question répond à oui, pensez à la meilleure façon de mettre en œuvre cela. Le constructeur devrait-il vraiment prendre une liste? Ou la classe elle-même devrait-elle fournir un
ajouter code> et un
supprimer la méthode code>. Au moment où vous avez conçu un département comme ayant une liste contenant des utilisateurs. Mais vous devez concevoir un département comme ayant des utilisateurs. C'est une différence!
@Jbnizet vraiment? Et comment l'appelant peut archiver cette référence?
@Andreemoniy Il s'agit d'une question de conception fondamentale. En fait, il est faux de disposer d'un constructeur d'accepter un argument de liste!
Liste mutable = nouvelle arrayliste <> (); Département D = nouveau département (mutable); mutable.add (nouvel utilisateur ()); code>
@Jbnizet ARH, tu veux dire ça. D'accord
Ooops! J'avais tort avec mon premier commentaire. OP est la copie du contenu, pas simplement la copie de la référence! Honte sur moi ...