Вам понадобится Reflection в какой-то момент из-за видимости.Если вы можете сразу принять Reflection и не использовать его снова, это, вероятно, было бы идеально, да?
Вы можете поместить метод getInstance()
в скрытый интерфейс (расположенный в том же пакете, что иIMyClass
, MyClassImpl
и A
, но не ClientOfA
), а затем передайте прототип от 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();
}
}
Для этого решения потребуется Reflection для созданияэкземпляр прототипа MyClassImpl
, который может быть выполнен с помощью Spring (или какой-либо другой формы внедрения зависимости).Он использует шаблон Prototype, шаблон Factory-метода и с готовностью поддерживает шаблон Singleton / Pool, но помните, что использование большего количества шаблонов проектирования не всегда лучше.Фактически, это может сделать дизайн (и код) более сложным и трудным для понимания новичком.
Для справки, единственная причина, по которой я бы даже подумал о защите этого решения, состоит в том, что оно требует отраженияударить один раз, вперед, а не каждый раз, когда вызывается createMyClass()
, что на оригинальном плакате указывало, что он / она будет часто.