通用接口 vs 每种类型的接口

4

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

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

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

但这种方法的缺点是我必须为每种类型的对象(X,y等)暴露一个接口,如果有许多这样的对象,我最终将暴露太多接口。我想通过仅公开一个处理基本类型对象的接口来处理此问题。

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

实现者编写自己的实现来处理类型为 X 的对象。
class XProcessor implements Processor<X> {
    void process(X object) {
        //do something
    }
}

这种方法的问题在于,当我需要在运行时调用process方法时,我不知道应该传递哪种类型的对象给处理器,因为在运行时我无法确定处理器的类型。
void process(Processor p) {
    p.process(??);
}

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

1
这里的问题是:为什么你真的需要在运行时知道类?如果你无法将过程概括化,那么就针对每个类进行处理。 - Luiggi Mendoza
1
这个问题可以通过为不同的“处理器”使用“工厂”来解决吗? - tredontho
3个回答

2
如@tredontho所建议的,可以使用一个工厂“ProcessorFactory”来获取相关实例,然后调用process方法。
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

    }

}

1
这看起来很干净。然而在我的情况下,接口“Processor”将向用户公开并由其实现。在运行时,我们将获取实现“Processor”接口的所有类,并调用它们的“process”方法。因此,除非我们针对每种类型的对象都有一个像“XProcessor”这样的接口,否则无法确定在运行时要传递哪种类型的对象到“process”方法中。所以在我的情况下,我认为单个通用接口是不够的,我应该为每种类型的对象公开一个接口。 - themanwhosoldtheworld
1
@Kalyan 你可以在 Processor 接口中引入 'Class<E> getSupportedClass();' 方法,并强制接口的实现者公开支持的类。通过使用这个方法,你可以找出哪个 Processor 实现适用于给定的 Base 实例。 - Dev Blanked
嗯,那应该不错,虽然看起来不太优雅。 - themanwhosoldtheworld

1

这与运行时无关。如果您编写类似以下代码,则已经在编译时删除了类型信息:

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);
}

1

process()方法一定需要一个参数吗?

你可以按照以下方式进行操作吗?

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

你可以这样做:

List<Processor> p = new ArrayList<>();
p.add(new Xprocessor);
p.add(new Yprocessor);

for each(Processor pr: p) {
   pr.Processor();
}

而多态性将负责其余部分。

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


那就是访问者模式。 - Riga

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接