设计模式问题



我有一个问题想很好地解决:

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()方法放在隐藏接口上(与IMyClassMyClassImplA位于同一个包中,但与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(),而最初的海报表明他/她会经常这样做。

最新更新