Object-oriented languages are good when you have a fixed set of
operations on things,and as your code evolves,you primarily add new
things. This can be accomplished by adding new classes which implement
existing methods,and the existing classes are left alone.Functional languages are good when you have a fixed set of things,and
as your code evolves,you primarily add new operations on existing
things. This can be accomplished by adding new functions which compute
with existing data types,and the existing functions are left alone.
说我有一个动物界面:
public interface Animal { public void speak(); }
我有一只狗,猫,鱼和鸟,都实现了界面.如果我想为Animal命名为jump()添加一个新方法,我将不得不通过我的所有子类并实现jump().
访问者模式可以缓解这个问题,但似乎Java 8中引入了新的功能特性,我们应该能够以不同的方式解决这个问题.在scala中,我可以很容易地使用模式匹配,但Java并没有真正拥有.
Java 8实际上使现有的东西更容易添加新的操作吗?
解决方法
当将此模式与新的Java 8可能性进行比较时,以下内容变得明显:
> Java 8允许轻松定义包含单个函数的操作.当处理像Iterable.forEach
,Stream.forEach
,Stream.reduce
这样的平面均匀收藏时,这样就很方便
访客允许定义多个功能,这些功能是通过数据结构的元素类型和/或拓扑来选择的,当处理异构集合和非平面结构时,例如单个功能特征停止工作时变得有趣.物品树
因此,新的Java 8功能永远不会成为访问者模式的替代品,然而寻找可能的协同效应是合理的. This answer讨论了改进现有API(FileVisitor)以启用使用lambda表达式的可能性.该解决方案是一个专门的具体访问者实现,可以为每个访问方法指定相应的功能.如果每个函数是可选的(即每个访问方法都有一个合理的默认值),如果应用程序只对一小部分可能的操作感兴趣,或者如果想要对其中的大部分进行统一处理,它将会很方便.
如果这些用例中的某些被认为是“典型的”,则可能会有接受方法采取一个或多个功能,在场景后创建适当的委托访问者(在设计新的API或改进您的控制下的API时).不过,我不会放弃普通接受(XyzVisitor),因为使用访问者的现有实现的选项不能低估.
如果我们将Collector
视为Stream的一个访问者,那么Stream API中也有类似的重载过载.它由多达四个功能组成,这是最大的想象力,可以访问一个平坦的,同质的项目序列.而不是必须实现该接口,您可以启动reduction specifying a single function或mutable reduction using three functions,但是通常情况下,specifying an existing implementation更简洁,例如collect(Collectors.toList())或collect(Collectors.joining(“,”))比通过lambda表达式/方法引用指定所有必要的函数.
当向访问者模式的特定应用程序添加此类支持时,它将使呼叫站点更加有光泽,而特定接受方法的实现站点始终是简单的.所以唯一仍然笨重的部分是访客类型本身;当增加支持基于功能接口的操作时,甚至可能会变得更加复杂.在不久的将来,不可能有一个基于语言的解决方案,更简单地创建这样的访问者或替代这个概念.