使用泛型重构多个重载方法

时间:2015-09-05 11:35:38

标签: java generics overloading

我有一个包含几个重载方法的类,例如:

interface SharedInterface
{
   public void commonMethod();
}

class Model1 implements SharedInterface
{
   public void commonMethod(){}
   public int foo(){ return 1; }
}

class Model2 implements SharedInterface
{
   public void commonMethod(){}
   public String bar(){ return "2"; }
}

class Client
{
   private ExternalClass external = new ExternalClass();

   public void handle( Model1 model )
   {
       external.calculate( model.foo() );
   }

   public void handle( Model2 model )
   {
       external.calculate( model.bar() );
   }
}

我想让Client类更通用,以便将来可以处理任何类型的Model。但是,因为每个Model都有自己特定的公共方法,所以Client.handle()方法需要根据给定的Model更改其行为。例如,如果给出了Model1实例,则调用该模型的方法foo();如果给出了Model2实例,则调用方法bar()等。将来会创建更多类型的模型。以下解决方案打破了开放的封闭原则,似乎是一种非常糟糕的做法:

class Client
{
   private ExternalClass external = new ExternalClass();

   public void handle( SharedInterface model )
   {
       if( model instanceof Model1 )
          external.calculate( model.foo() );
       else if( model instanceof Model2 )
          external.calculate( model.bar() );
   }
}

我正在考虑使用泛型,但我不确定泛型如何解决这个问题。

请注意,Client类具有依赖项(使用库)。模型必须是POJO,不依赖于任何其他类。因此,由于Client.handle()的实现使用了这些依赖项,因此无法在Model类中移动该方法。

有人可以提供一些替代方案吗?

2 个答案:

答案 0 :(得分:1)

访客设计模式最适合您的问题...链接可以帮助您 https://sourcemaking.com/design_patterns/visitor ..

答案 1 :(得分:1)

您的处理逻辑因每种类型而异,并且必须在某处描述不同的行为,对于您添加的每个Model,您必须拥有一条处理逻辑,这是的完美案例重载 - 您已在第一个代码位中执行此操作。

如果您已经确定Client清除这些实施。您可以在数据POJO的包装器(适配器)中定义不同的处理逻辑,并将它们传递给handle(),例如:

class Client {
    private ExternalClass external = new ExternalClass();

    public void handle(PojoAdapter<?> model) {
        model.getExecuted(external);
    }
}

// Actually, generics are not necessary here, just to
// avoid declaring the same model field with different type
// in each implementation
abstract class PojoAdapter<T extends SharedInterface> {
    protected T model;
    public PojoAdapter(T model) {
        this.model = model;
    }
    public abstract void getExecuted(ExternalClass excls);
}

class Model1Adapter extends PojoAdapter<Model1> {
    @Override public void getExecuted(ExternalClass excls) {
        external.calculate(model.foo());
    }
}

class Model2Adapter extends PojoAdapter<Model2>{
    @Override public void getExecuted(ExternalClass excls) {
        external.calculate(model.bar());
    }
}