Je recherche différentes façons de garantir que chaque instance d'une classe donnée est une instance identifiable de manière unique.
Par exemple, j'ai une classe Name
avec le champ name
. Une fois que j'ai un objet Name
avec name
initialisé à John Smith, je ne veux plus pouvoir instancier un autre objet Name
avec le nom de John Smith, ou si l'instanciation a lieu, je veux qu'une référence à l'objet d'origine soit renvoyée plutôt qu'un nouvel objet.
Je suis conscient qu'une façon de faire est d'avoir une fabrique statique qui contient un Map
de tous les objets Name actuels et la fabrique vérifie qu'un objet avec John Smith comme nom n'existe pas déjà renvoyer une référence à un objet Name
.
Une autre façon dont je pourrais penser du haut de ma tête est d'avoir une carte statique dans la classe Name
et lorsque le constructeur est appelé levant une exception si la valeur transmise pour name
est déjà dans utiliser dans un autre objet, cependant je suis conscient lancer des exceptions dans un constructeur est généralement une mauvaise idée .
Y a-t-il d'autres moyens d'y parvenir?
En fait, vous avez déjà répondu à votre question. Votre première façon devrait être plus efficace ici. Utiliser static factory
Est toujours préférable à constructor
partout où vous pensez que vous le pouvez. Ainsi, vous pouvez éviter d'utiliser Constructor
dans ce cas, sinon vous auriez throw some exception
Si une instance existe déjà avec le nom donné.
Ainsi, vous pouvez créer une méthode d'usine statique: - getInstanceWithName(name)
qui obtiendra l'instance déjà disponible avec ce nom, et si elle n'existe pas, elle créera une nouvelle instance et fera votre constructor
privé, comme cela doit être fait principalement lorsque vous traitez avec static factories
.
De plus, pour cela, vous devez conserver un List
ou Map
statique de toutes les instances uniques créées, dans votre classe Factory
.
[~ # ~] modifier [~ # ~] : -
Vous devriez certainement passer par - Efficace Java - Item # 1: Considérez les usines statiques plutôt que les constructeurs . Vous ne pouvez pas obtenir une meilleure explication que ce livre.
Mentions de Java efficace semble ajouter beaucoup de crédibilité, donc cette réponse s'appuie sur:
Je prendrais un peu de recul et me demander pourquoi vous vous souciez s'il y a plus d'une instance de cet objet de nom.
J'ai rarement besoin de faire ce type de mise en commun d'objets. Je pense que l'OP fait cela afin qu'ils puissent simplement comparer leurs objets Name
avec ==
. Ou utilisez les objets Name
à l'intérieur d'un HashMap
ou similaire comme clé.
Si c'est le cas, c'est quelque chose qui peut être résolu par implémentation correcte de equals()
.
Ainsi:
public final class Name {
private final String name;
public Name(String name) {
if (name == null) {
name = ""; //or exception if you like
}
this.name = name;
}
public String getName() {
return name;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof Name)) {
return false;
}
Name other = (Name) o;
return other.name.equals(name);
}
@Override
public int hashCode() {
return name.hashCode();
}
}
Une fois cela fait, ce qui suit est vrai:
Name a = new Name("weston");
Name b = new Name("weston");
assert(a.equals(b)); //same but:
assert(a!=b); //not the same instance
//test out the Name instances in a hashmap:
HashMap<Name,Object> map = new HashMap<Name,Object>();
Object detailsIn = new Object();
map.put(a,detailsIn);
Object detailsOut = map.get(b);
assert(detailsIn==detailsOut); //the map returned the same details object
//even though we put with `a` and got with `b` thanks to our correct equals implementation
Je devine votre objectif, mais de cette façon, vous pouvez utiliser la classe Name
dans les cartes de hachage, etc., et elles pas doivent être exactement la même instance.
Name
une interfaceNameFactory
avec une méthode Name getByName(String)
NameFactory
avec un Map<String,WeakReference<Name>>
à l'intérieursynchronize
sur la carte par nom à l'intérieur de la méthode getByName
avant de créer de nouvelles instances de Name
Name
dans votre implémentation de NameFactory
Cette approche vous permettrait de vous assurer que:
Name
existe à tout moment,Name
s restent plus longtemps que nécessaire,vous devez rendre les constructeurs privés et créer des méthodes comme getNameInstance(String)
, si un objet du même nom existe déjà (basé sur une classe statique hastable par exemple), vous retournez cette référence, sinon vous créez un nouvel objet en utilisant votre constructeur privé et ajoutez-le à la table de hachage
Essayez de suivre. Vous devez garder une trace de chaque objet que vous créez. À cette fin, j'utilise List. Et a rendu le constructeur de classe privé, afin que la pré-vérification puisse être appliquée avant de créer une instance
class UniqueName
{
private string Name;
public int ID;
private static int Count=0;
static List<UniqueName> lt=new List<UniqueName>();
private UniqueName(string Name)
{
this.Name = Name;
ID = ++Count;
}
public static UniqueName GetUniqueueInstance(string Name)
{
foreach (UniqueName un in lt)
{
if ( string.Compare( un.Name,Name,StringComparison.InvariantCultureIgnoreCase)==0)
return un;
}
UniqueName temp=new UniqueName(Name);
lt.Add(temp);
return temp;
}
}