标签 :设计模式
引言
一个学校可能每天有不同的领导过来巡视检查,今天来一个教育局领导检查教育实施工作,明天来一个卫生局的领导检查食堂卫生,后天来一个公安局的领导检查安全消防安全设备。
每一个领导会带着不同的目的来访问学校。
教育局领导的工作内容包括教育方针研讨会、课堂旁听和教师慰问;卫生局领导的工作内容包括检查食堂厨房卫生、食品安全研讨会等;公安局领导的工作内容包括设备巡查、消防演练、安全教育视频观看等。
这时领导是一个访问者(Visitor),学校是一个数据元素(Element),工作内容就是访问者的具体方法(VisitConcreteElementXXX)。学校只负责接待各位领导,而各级领导才知道自己具体做的事情。如果领导临时决定要修改工作内容,学校不需要知道,且不需要做任何改变。这就是访问者模式。
类型
行为型模式。
目的
将数据结构与数据操作分离。
访问者模式的目的是封装一些施加于某种数据结构元素之上的操作,这些操作可能是多个其他操作的组合,一旦这些操作需要修改的话,接受这个操作的数据结构可以保持不变。为不同类型的元素提供多种访问操作方式,且可以在不修改客户端代码的情况下增加新的操作方式,这就是访问者模式的模式动机。
UML类结构
角色
Vistor: 抽象访问者。为该对象结构中的ConcreteElement的每一个类声明的一个操作。
ConcreteVisitor: 具体访问者。实现Visitor申明的每一个操作,每一个操作实现算法的一部分。
Element: 抽象元素。定义一个Accept操作,它以一个访问者为参数。
ConcreteElement: 具体元素 。实现Accept操作。
ObjectStructure: 对象结构。一般是一个容器,如List、Set或者Map,能够枚举它的元素,可以提供一个高层的接口来允许访问者访问它的元素。
优势
(1)符合单一责任原则:即把数据对象的操作单独封装起来,使完成同一个功能的多种操作封装到一个操作中,且客户端无需感知。
(2)Visitor的扩展性良好:如要对数据对象产生新的操作,只需封装一个新的ConcreteVisitor即可。
不足
因为Visitor封装了对所有数据元素的操作,所以如果要添加一个新的数据元素(即ConcreteElement),则需要修改Visitor接口和实现了该接口的所有ConcreteVisitor,这方面的扩展性不好。所以访问者模式最好用在数据元素已经完全确定的情况,比如项目重构的情况。
具体使用说明
Client端需要操作一个数据元素时,只需要让该元素accept一个ConcreteVisitor。一旦需要改变操作的具体细节,不需要修改Client端,只需要修改ConcreteVisitor的VisitConcreteElementXXX方法的具体实现即可。