Vous aurez besoin de réflexion à un moment donné en raison de la visibilité. Si vous pouvez accepter Reflection une fois et ne pas l'utiliser à nouveau, ce serait probablement idéal, oui?
Vous pouvez mettre une méthode getInstance()
sur une interface cachée (situé dans le même paquet que IMyClass
, MyClassImpl
et A
, mais pas ClientOfA
), puis passer un prototype de MyClassImpl
-A.init()
.
// -- You wish you would have thought of the word prototypeable! ...maybe?
interface IMyClassPrototypeable extends IMyClass
{
public IMyClass getInstance();
}
class MyClassImpl implements IMyClassPrototypeable // -- and IMyClass by extension.
{
// -- Still not visible outside this package.
public IMyClass getInstance()
{
return new MyClassImpl();
}
}
class A
{
private IMyClassPrototypeable prototype;
// -- This method is package-private.
void init(IMyClassPrototypeable prototype)
{
this.prototype = prototype;
}
public IMyClass createMyClass()
{
return prototype.getInstance();
}
}
Cette solution nécessiterait réflexion pour créer l'instance prototype de MyClassImpl
, ce qui pourrait être fait via Spring (ou une autre forme d'injection de dépendance). Il utilise le pattern Prototype, le pattern Factory-method, et supporte facilement le pattern Singleton/Pool, mais rappelez-vous que plus de patterns de design utilisés ne sont pas toujours meilleurs. En fait, cela peut rendre le design (et le code) plus complexe et plus difficile à comprendre pour un débutant. Pour l'anecdote, la seule raison pour laquelle je pense à préconiser cette solution, c'est parce qu'elle prend la réflexion une fois, à l'avant, plutôt qu'à chaque fois que createMyClass()
est appelée, ce que l'affiche originale indiquait fréquemment.
Vous pouvez prendre note que vos conventions de codage sont non standard. I pour les déclarations d'interface et les majuscules pour une méthode ne sont généralement pas utilisés en Java. (Certains vont argumenter sur l'interface, mais Eclipse est le seul morceau majeur de code que j'ai jamais vu utilisé). – Robin