3

假设我有一个带有一个参数的方法,并且根据参数的类型,该方法应该做不同的事情。

让我们调用方法doMethod()

private int doMethod(Class1 x) {
    // do something with x
}

private int doMethod(Class2 x) {
   // do someting else with x
}

...

我有几种这样的方法。现在我的问题来了:我有一个不同的方法,它接受一个参数,它是上面所有其他类的超类(但实际上它总是它的子类之一):

private void otherMethod(SuperClass obj) {
      // I do something clever with obj, 
      // which is the super class of Class1, Class2, .. Classn
      // however this method is always called with either Class1, Class2, etc.
      // never with an instance of SuperClass itself.

      // finally I want to execute doMethod() on obj:
      int result = doMethod(obj);        

      // fails because doMethod(SuperClass) does not exist
}

所以最后我最终创建了一个doMethod(Superclass obj),检查 obj ,instanceof然后doMethod()使用演员表调用。

必须有更好的方法来做到这一点,不是吗?我现在想不出来,所以也许有人可以帮助我:)

非常感谢!

4

1 回答 1

2

几种可能性:

子类 + 访问者模式

如果不是最终的,您可以为每个子类创建一个子类。您可以让他们提供一种方法并使用访问者模式visit()实现您的附加操作。doMethod()这将打开以后添加不同操作的可能性。如果操作正确,访问者模式应该不会忘记将操作添加到新的子类(因为它不会编译)。这可能是也可能不是一件好事,这取决于您的需要。

子类是我喜欢的解决方案的一部分。这里有爆炸类层次结构和复杂性的危险:如果可能的话,我会让你添加的额外子类成为 final。如果您要扩展的任何类在将来成为最终类,您也会遇到麻烦(向后兼容中断,但并非不可能)。

此处的示例:http ://www.javacodegeeks.com/2013/08/visitor-design-pattern-in-java-example-tutorial.html (在此示例中,开发人员可以访问基类并在visit()那里添加方法,而您必须将其添加到由您的额外子类实现的通用接口中)。

聚合+访客模式

上面的一个变体是创建一个并行的类层次结构,其中您自己的类包含(而不是子类)来自其他层次结构的类的实例。您添加visit()到您自己的类层次结构(以及您想要的任何其他方法),并提供访问底层类型的方法。您应该能够将其很好地包装在泛型中。

不过,同样,这里可能存在很多复杂性。

'处理程序'的地图

您可以在以实例类型为键的映射中将操作查找为接口的实现。

// Java-y pseudo-code...
Map<Class<? extends SuperClass>,Function<V,R>> doMethods = new HashMap<>();
doMethods.add(FooClass.class, FooDoMethod.INSTANCE);
doMethods.add(BarClass.class, BarDoMethod.INSTANCE);
...
public R doMethod(V it) {
    Class<? extends V> cls = it.getClass();
    Function<? extends V,R> fn = doMethods.get(cls);
    if(fn==null)
        throw new UnsupportedOperationException(
            "Can't doMethod() on a "+cls.getName());
    return fn.apply(it);
}

这里的INSTANCE单例对象将实现类似于FunctionJava 1.8(或 1.8 之前的 Comparable)中的新接口 - 即是具有实现操作的单个方法的接口的实现。然后,您可以通过向映射添加更多条目来扩展支持该操作的类型。您将需要为每种支持的类型添加一个显式条目(即使是中间基类,如果它们实际上可以具有实例 - 类似于 Swing 中的 JComponent 和 JButton(两者都可以存在真实实例)。当然,您可以,为多种类型添加相同的实现,如果它们以相同的方式实现。

然后,您可以在其他类中隐藏对映射处理程序(和映射本身)的调度。

(PS对不起,手头没有javac,否则我会正确尝试这些。)

于 2013-11-11T15:42:53.790 回答