Java 8默认方法实现访问者模式

9

访问者模式(双重分派)在其本身就是非常有用的模式,但它经常被指责破坏接口,如果任何新成员被添加到继承层次结构中,这是一个有效的观点。

但是,在Java 8引入默认方法之后,现在我们可以在接口中定义默认实现,客户端接口将不会被破坏,客户端可以根据需要优雅地采用更改后的接口。

interface Visitor{
   public void visit(Type1 type);
   public void visit(Type2 type);

   //added after the first version of visitor is released
   default public void visit(NewType type){
        //some default implementation
   }
}

现在使用默认方法,如果未来引入新类型NewType,不会再破坏客户端代码。

这样改进后的Visitor模式更易于接受和使用吗?


12
个人而言,我认为接口的破坏大多数情况下都是有好处的,因为它迫使你在每个地方都小心处理新类型,不用像使用 instanceof 测试链那样担心遗漏某个地方。将新的 visit() 方法实现为默认方法会提供一个默认实现,但我想99%的情况下都是错误的。如果你知道它在运行时不会执行应该做的事情,谁会关心代码仍然可以编译? - JB Nizet
@JBNizet 是的。只是访问者模式有一个我认为不再适用的缺点。但我明白为什么不应该使用默认方法与访问者模式。 - Narendra Pathai
我同意,访问者模式在我看来主要是关于编译错误的。如果代码在运行时之前没有出现问题,也就是在客户端出现问题,那就太晚了。 - Desty
1个回答

4
您的问题中包含了这样一个假设: Visitor 必须是一个 interface。由于 Visitor 模式并不是特定于 Java 的,因此它并不强制要求这样的实现。
事实上,全世界有很多使用 abstract 类作为 Visitor 或使用 interface 但同时提供一个 abstract 实现类的用例。
虽然这个评论指出了在编译时检测未处理情况的可能性,但这仅适用于每个访问者始终必须为每个 visit 方法提供实现的情况。当您有很多情况时,这可能会导致代码膨胀(并可能导致其他开发人员为他们的访问者编写自己的 abstract 基类)。
正如所说,不是每个人都以这种方式使用 Visitor 模式。许多实现使用 abstract 类来提供空的 visit 方法或将 visit 方法委托给另一个采用更抽象类型的 visit 方法。对于这些实现,添加新类型从来不是问题。
回答您的问题,当以不强制每个 Visitor 为每个方法提供实现的方式使用 Visitor 模式时,使用接口中的 default 方法是一种选择。但它并没有使 Visitor 模式“更易采用和有用”,因为它本来就没有真正的问题。使用 abstract 访问者类的选项始终存在。

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