【问题标题】:Generic interface vs interface for each type每种类型的通用接口与接口
【发布时间】:2013-10-08 14:35:23
【问题描述】:

有两个类 X、Y 实现了 Base 接口 有一个接口负责处理每种类型的对象

interface Base {
}
class X implements Base {
}
class Y implements Base {
}

interface XProcessor {
    void process(X object);
}
interface YProcessor {
    void process(Y object);
}

但是这种方法的缺点是我必须为每种类型的对象(X,y..)公开一个接口,如果有很多这样的对象,我最终会暴露太多接口。我想我会通过只公开一个接口来处理这个问题,该接口负责处理 Base 类型的对象

interface Processor<E extends Base> {
  void process(E object);
}

实现者编写自己的实现来处理类型 X 的对象

class XProcessor implements Processor<X> {
    void process(X object) {
        //do something
    }
}

这种方法的问题是当我必须调用方法进程时,在运行时,我不知道应该将哪种类型的对象传递给处理器,因为在运行时我无法确定该处理器的类型

void process(Processor p) {
    p.process(??);
}

有没有更好的方法来处理这个问题?

【问题讨论】:

  • 这里的问题是:为什么你真的需要在运行时知道类?如果您无法概括该过程,请使用每个班级。
  • 这可以用Factory 处理不同的Processors 吗?

标签: java generics generic-programming type-erasure


【解决方案1】:

正如@tredontho 所建议的,可以使用如下所示的工厂“ProcessorFactory”来获取相关实例,然后调用流程方法

public class ProcessTest {

    <T extends Base> void processBase(T base) {
        ProcessorFactory.getProcessor(base).process(base);
    }

}


interface Base{
}
class X implements Base{
}
class Y implements Base{
}

interface Processor<E extends Base>{
    void process(E object);
}

interface XProcessor extends Processor<X> {

}
interface YProcessor extends Processor<Y> {

}

class ProcessorFactory {

    @SuppressWarnings("unchecked")
    static <T extends Base> Processor<T> getProcessor(T base) {
        if (base instanceof X) {
            return (Processor<T>) new XProcessorImpl();
        }
        return null;
    }

}

class XProcessorImpl implements XProcessor {

    @Override
    public void process(X object) {
        // TODO Auto-generated method stub

    }

}

【讨论】:

  • 这看起来很干净。但是,在我的情况下,接口“处理器”将公开给用户,他将实现它。在运行时,我们将获取所有实现“处理器”接口的类并调用它们的“进程”方法。再说一次,除非我们为每种类型的对象都有一个接口,例如用于类型“X”的对象的“XProcessor”,否则无法确定在运行时将哪种类型的对象传递给 process 方法。所以在我的情况下,我认为单个通用接口是不够的,我应该为每种类型的对象公开一个接口。
  • @Kalyan 你可以介绍 'Class getSupportedClass();'到处理器接口并强制接口的实现者公开支持的类。通过使用它,您可以确定用于给定 Base 实例的处理器实现
  • 嗯,应该不错,虽然看起来不太优雅。
【解决方案2】:

这与运行时无关。如果您编写类似

的内容,您已经在编译时删除了类型
void process(Processor p){
  p.process(??);
}

如果你的Processor 接口是通用的,你不应该再使用原始类型:

<E extends Base> void process(Processor<E> p){
  p.process(…instance of E…);
}

例如:

<E extends Base> void processAll(Processor<E> p, Collection<? extends E> c){
  for(E item: c) p.process(c);
}

【讨论】:

    【解决方案3】:

    process()方法有参数吗?

    你可以走下面的路吗?

    每个单独的类都实现了公共接口processor,其中包括void process() 方法的存根,从而创建了它们的自定义操作。然后你可以upcast 你的对象到接口(如果是的话,把它们放在某种集合中必需的)。

    你可以有类似的东西:

    List<Processor> p = new ArrayList<>();
    p.add(new Xprocessor);
    p.add(new Yprocessor);
    
    for each(Processor pr: p) {
       pr.Processor();
    }
    

    而多态性将负责其余的工作。

    在这种情况下,您甚至不需要泛型。

    【讨论】:

    • 这就是访问者模式。
    猜你喜欢
    • 1970-01-01
    • 2017-05-28
    • 2018-11-18
    • 2020-08-10
    • 2022-11-28
    • 2020-09-29
    • 1970-01-01
    • 1970-01-01
    • 2014-05-20
    相关资源
    最近更新 更多