我有一个问题想很好地解决:
public interface IMyclass
{
}
public class A
{
public void Init(IMyclass class){?}
public IMyclass CreateMyClass(){?}
}
在系统开始时,我想使用Init()定义IMyClass的动态类型,在系统运行期间,我想创建我在Init定义的类型的新实例。
注意事项:
1.IMyclass必须是接口
2.IMyclass的动态类型只有在init时才知道(在:之后我没有构造函数)
3.我可以在IMyclass使用反射或定义方法克隆,有更好的解决方案吗?
谢谢。
您可以将提供程序传递到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();
}
}
请注意,如果在CreateMyClass
之前没有调用Init
,这两个例子都会失败,您需要进行一些检查,或者更好的做法是在构造函数中进行初始化。
我正确理解这个问题了吗?
这是一种依赖注入,您应该阅读:
- http://en.wikipedia.org/wiki/Dependency_injection
- http://www.martinfowler.com/articles/injection.html#FormsOfDependencyInjection
基本上,您有一个类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)
如果您只想在CreateMyClass()
中实例化同一个类,而不需要进一步配置,则可以使用反射。
public class A
{
private Class prototype;
public void Init(IMyClass object) {
this.prototype = object.getClass();
}
public IMyClass CreateMyClass() {
return prototype.newInstance();
}
}
我怀疑你想要的不仅仅是这个,如果是这样,你需要解释你想如何使用这个。您可能正在查找Builder或Factory模式。
由于可见性的原因,您将在某个时刻需要反射。如果你可以接受反射一次,而不必再使用它,那可能是理想的,是吗?
您可以将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(或某种其他形式的依赖注入)来完成。它使用原型模式、工厂方法模式,并很容易支持Singleton/Pool模式,但请记住,使用更多的设计模式并不总是更好的。事实上,它会使设计(和代码)更加复杂,初学者更难理解。
记录在案,我甚至会考虑提倡这种解决方案的唯一原因是,它会在前面进行一次反思,而不是每次调用createMyClass()
,而最初的海报表明他/她会经常这样做。