我有一个我想要解决的问题:
public interface IMyclass
{
}
public class A
{
public void Init(IMyclass class){?}
public IMyclass CreateMyClass(){?}
}
在系统开始时,我想通过使用Init()来定义动态类型的IMyClass,并且在系统运行期间,我想创建我在init中定义的类型的新实例。
笔记:
1。 IMyclass必须是接口
2。只在init时才知道的动态类型的IMyclass(我之后没有构造函数):)
3。我可以使用反射或定义方法克隆在IMyclass有没有更好的解决方案?
谢谢。
答案 0 :(得分:2)
您可以将提供商传递给class A
public class A
{
IMyClassProvider _provider;
public void Init(IMyClassProvider provider)
{
_provider = provider;
}
public IMyclass CreateMyClass()
{
return _provider.Create();
}
}
或者可能使用构造函数委托
public class A
{
Func<IMyclass> _ctor;
public void Init(Func<IMyclass> ctor)
{
_ctor = ctor;
}
public IMyclass CreateMyClass()
{
return _ctor();
}
}
请注意,如果在Init
之前未调用CreateMyClass
,则这两个示例都会爆炸,您需要进行一些检查,或者更好的是在构造函数中执行初始化。
我是否正确理解了这个问题?
答案 1 :(得分:2)
这是一种依赖注入,您应该阅读:
基本上,您有一个类A
,它在初始化时填充了工厂(或提供者)。然后,您使用A
而不是调用new
。
一个简单的例子:
interface Provider<V> {
V instance(Object... args);
}
class Dispatch {
// you can make a singleton out of this class
Map<Class, Provider> map;
<T> void register(Class<T> cl, Provider<? extends T> p) {
// you can also bind to superclasses of cl
map.put(cl, p);
}
<T, I extends T> void register(Class<T> cl, final Class<I> impl) {
register(cl, new Provider<I>() {
I instance(Object... args) {
// this class should be refactored and put in a separate file
// a constructor with arguments could be found based on types of args values
// moreover, exceptions should be handled
return impl.newInstace();
}
});
}
<T> T instance(Class<T> cl, Object... args) {
return map.get(cl).instance(args);
}
}
// usage
interface MyIf { ... }
class MyIfImpl implements MyIf { ... }
Dispatch d = new Dispatch();
d.register(MyIf.class, new Provider<MyIf>() {
MyIf instance(Object... args) {
return new MyIfImpl();
}
});
// or just
d.register(MyIf.class, MyIfImpl.class);
MyIf i = d.instance(MyIf.class);
编辑:
已添加register(Class, Class)
答案 2 :(得分:1)
如果您只想在CreateMyClass()
中实例化同一个类而无需进一步配置,则可以使用反射。
public class A
{
private Class prototype;
public void Init(IMyClass object) {
this.prototype = object.getClass();
}
public IMyClass CreateMyClass() {
return prototype.newInstance();
}
}
答案 3 :(得分:1)
由于可见性,您在某些时候需要反思。如果您可以预先接受反射,而不必再次使用它,那可能是理想的,是吗?
您可以将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-method模式,并且很容易支持Singleton / Pool模式,但请记住,使用的更多设计模式并不总是更好。事实上,它可以使设计(和代码)更复杂,更难以让初学者理解。
为了记录,我甚至考虑提倡这种解决方案的唯一原因是因为它需要反射一次,而不是每次调用createMyClass()
,原始海报表明他/她会经常这样做。