设计模式问题

时间:2011-05-27 17:53:23

标签: java oop design-patterns reflection

我有一个我想要解决的问题:

public interface IMyclass
{
} 
public class A
{
   public void Init(IMyclass class){?}
   public IMyclass CreateMyClass(){?}
}

在系统开始时,我想通过使用Init()来定义动态类型的IMyClass,并且在系统运行期间,我想创建我在init中定义的类型的新实例。

笔记:
1。 IMyclass必须是接口
2。只在init时才知道的动态类型的IMyclass(我之后没有构造函数):)
3。我可以使用反射或定义方法克隆在IMyclass有没有更好的解决方案?

谢谢。

4 个答案:

答案 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();
    }
}

我怀疑你想要更多,如果是这样,你需要解释你想如何使用它。您可能正在寻找BuilderFactory模式。

答案 3 :(得分:1)

由于可见性,您在某些时候需要反思。如果您可以预先接受反射,而不必再次使用它,那可能是理想的,是吗?

您可以将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(或其他形式的依赖注入)来完成。它使用Prototype模式,Factory-method模式,并且很容易支持Singleton / Pool模式,但请记住,使用的更多设计模式并不总是更好。事实上,它可以使设计(和代码)更复杂,更难以让初学者理解。

为了记录,我甚至考虑提倡这种解决方案的唯一原因是因为它需要反射一次,而不是每次调用createMyClass(),原始海报表明他/她会经常这样做。