Polymorphic factory / getInstance () en Java
Je vise à créer un ensemble d'objets, dont chacun a un identifiant unique. Si un objet existe déjà avec cet identifiant, je veux utiliser l'objet existant. Sinon je veux en créer un nouveau. J'essaie de ne pas utiliser le mot Singleton, parce que je sais que c'est un gros mot ici...
Je peux utiliser une méthode de fabrique:
//A map of existing nodes, for getInstance.
private static Map<String, MyClass> directory = new HashMap<String, MyClass>();
public static MyClass getInstance(String name) {
MyClass node = directory.get(name);
if(node == null) {
node == new MyClass(name);
}
return node;
}
Tout, je pouvais avoir une MyClassFactory méthode.
Mais je n'avais prévu à la sous-classe MyClass:
public class MySubClass extends MyClass;
Si je ne fais pas de plus, et d'invoquer MySubClass.getInstance():
MyClass subclassObj = MySubClass.getInstance("new name");
... puis subclassObj sera une plaine MyClass, pas un MySubClass.
Pourtant primordial getInstance() dans chaque sous-classe semble hacky.
Est-il une solution élégante, je suis absent?
C'est la version généralisée de la question. Plus de détails, depuis la answerers a demandé pour eux.
Le programme est pour la génération d'un graphe orienté de dépendances entre les nœuds représentant des morceaux de logiciel. Les sous-classes comprennent des programmes Java, Services Web, Stockées SQL procédures, message-driven triggers, etc.
De sorte que chaque classe "est-un" élément de ce réseau, et possède des méthodes permettant de naviguer et de modifier les relations de dépendance avec les autres nœuds. La différence entre les sous-classes sera la mise en œuvre de la populate()
méthode utilisée pour définir l'objet à partir de la source appropriée.
Disons que le nœud nommé 'login.java" apprend qu'il a une dépendance sur " checkpasswd.sqlpl':
this.addDependency( NodeFactory.getInstance("checkpasswd.sqlpl"));
Le problème est que le checkpasswd.sqlpl objet peut ou non existent déjà à ce moment.
source d'informationauteur slim
Vous devez vous connecter pour publier un commentaire.
La méthode statique est définie sur la classe mère, et elle est appelée de façon statique. Donc, il n'y a aucun moyen de savoir dans la méthode que vous avez appelé à la sous-classe. Le compilateur java probablement même se résout à l'appel de manière statique à un appel à la classe parent.
De sorte que vous aurez besoin soit de réimplémenter la méthode statique à votre enfant des classes que vous proposez, ou de les rendre non statique de sorte que vous pouvez l'héritage (sur une hiérarchie de l'usine objetset non des classes), ou de passer un paramètre pour indiquer le type que vous souhaitez créer.
Découvrez la EnumSet.noneOf() la méthode. Il a le même problème que vous, et il la résout en passant par le java.lang.Class la méthode. Vous pouvez utiliser newInstance sur la classe. Mais personnellement, je voudrais utiliser une fabrique des objets plutôt que des classes avec des méthodes statiques.
Avez-vous regardé dans Guice? Vous ne savez pas si il permettrait de résoudre votre problème exactement, mais il agit comme un générique de l'usine et le conteneur d'injection de dépendance, et élimine les non-sécurisée de type Chaîne de clés.
après lecture, vous explication du problème, je pense que votre ce qui rend très difficile pour vous-même par sous classement dans votre graphique de la construction. je pense que le problème devient beaucoup plus simple si vous vous séparez le graphe de dépendance de l "information sur le programme"
utiliser une Interface tels que:
et ensuite utiliser une usine à instancier vous nœuds
Vous semblent indiquer que quelque part vous savez dans quelle classe il devrait être si elle n'existe pas.
Si vous implémentez cette logique dans votre usine, vous devez obtenir les bonnes classes.
De cette façon, vous devriez aussi n'ont pas besoin de savoir ce que la classe fait a été renvoyé de l'usine.
Je voudrais également susceptible de rendre "MyClass" une interface si vous envisagez d'acheter un modèle de Fabrique.
La Classe class est paramétré avec le type de cas, il peut créer. (ex: Classe<String> est une usine pour des instances de Chaîne.)
Je ne vois pas de moyen de se déplacer à connaître le type de l'instance qui doit être créé lorsque vous getOrCreate à l'aide de la méthode de fabrique ici, donc je vous conseille de les passer à la méthode et de paramétrer le type généré:
Aussi, j'ai remarqué que vous n'étiez pas fait mettre de la nouvellement construit, des nœuds dans le répertoire - je suppose que c'est un oubli. Vous pouvez aussi surcharger cette méthode avec une autre qui n'a pas pris un générateur et codé en dur pour le type par défaut:
Vous voulez probablement l'injection de dépendance. Il serait de généraliser ce que vous essayez de faire un peu.
Aussi, l'Héritage n'est probablement pas exactement ce dont vous avez besoin. Ne jamais l'utiliser, sauf si vous pouvez passer le "est-un" test de. Si votre classe héritée "A-un" unique point de chaîne (essentiellement c'est ce que votre classe semble être) cela ne veut pas dire "est-un"...
Vous pourriez avoir l'un l'autre. Il ya probablement assez quelques solutions, mais A) vous n'avez pas publier l'intégralité de votre liste d'exigences ainsi nous ne pouvons que deviner, et B) ce que vous voulez probablement, c'est l'injection de dépendance. 🙂
Le modèle semble être une sorte de Poids mouche (de structure, si ce n'est un match parfait pour l'intention.)
La
populate
méthode, comme décrit, pourrait être mappé à laTemplate
modèle, bien qu'il n'est pas nécessairement de l'adresse exprimé des préoccupations.Ce que je vous suggère est une généralisation de l'usine, avec un
create
(au lieu degetInstance
ce qui implique un Singleton, pour moi en tout cas) pour la méthode de différents types que vous attendez.La connaissance de la façon dont un
name
des cartes pour un<differentiator>
est vraiment une mise en œuvre de choix. Idéalement, il y aurait une polymorphescreate
et la différenciation serait parnode
type. Lecreate
méthode renvoieMyClass
mais c'est vraiment le retour de la sous-classes. J'avais fortement envisager de faireMyClass
soit une interface ou une classe abstraite, avec uneabstract
populate
méthode (il y a leTemplate
).De la description, il semble vraiment que c'est la création d'un comportement qui est différente entre les types, pas le comportement de la sous-classes elles-mêmes, de sorte que le cas pour le refactoring de
MyClass
à une interface ou une classe abstraite devient plus fort.Pour paraphraser R. A. Heinlein,
TANSTAAFL
- Il N'y a pas une Telle Chose Comme Un Repas Gratuit -- quelque part la connaissance de la façon de créer les différents types d'exister dans l'application. Si votre choix est de mettre ces connaissances dans l'Usine de la classe, comme certains des autres réponses ont exprimé, ou de séparer la décision de ce mise en œuvre est créée à partir de comment il est créé. Il semble qu'il y est une capacité d'analyse d'un fichier système, et de percevoir lesNode
s d'elle. Ce code va (ou peut) connaître les type de laNode
(la réponse à la ce) qui devraient être créés.Si qui obtient mis en œuvre comme un
switch
ou dans un plus OO de la mode (l'une des fois où pilotée par un tableau de répartition serait bien) est à vous. Si c'est quelque chose qui pourrait être utile, je peux développer ici.BTW, si le comportement du cœur de
MyClass
doit être étendu ou modifié pour certaines sous-classes, qui est l'endroit où uneDecorator
pourrait être utile.Réponse Originale À Cette Question:
Vous pourriez envisager de la Décorateur ou Modèle Les Modèles De Conception comme des alternatives.