- CarElement
- 是各种接口的实现
- 轮子
- 引擎
- 整体框架
- 最后——它是一辆车
- 各个组件可对访问者暴露自己的细节
- 访问者拿着细节去做不同的事情,这些事情是和组件本身可能并无紧密关联的
- 以此做到具体操作和固有结构解耦
- 是各种接口的实现
意图
将数据结构和数据操作分离
解决问题
数据结构和数据操作耦合的问题
- 通常数据结构是稳定的
- 但数据操作是易变的
个人理解
访问者模式的应用场景一般需要具备两个条件:
- 相对稳定的被访问者,如数据结构、工具、组件等,自身具备足够的属性和基础能力
- 相对灵活可变、不确定的外部使用,对此数据结构、工具、组件的使用。
举例说明
被访问者:五金店
- 包含子节点
- 锤子
- 绳子
- 所接受的访问者:带钱就行
五金店 {
void accept(代钱的客户,要什么){
switch(要的东西){
case 锤子:
客户.给(锤子实例)//触发得到锤子
break
case 绳子:
客户.给(绳子实例)//触发得到绳子
break
default:
//没得给
}
}
}
访问者——带了钱的客户
- 进店问,有锤子吗?
一次购物体验 = new 五金店Visitor() {
void 得到锤子(锤子){
//去盖房子、去玩耍,随意
}
void 得到绳子(绳子){
//去绑箱子、其他,随意
}
//相当于visit 方法
void 开始购物(五金店, 要啥?) {
五金店.accept(带了钱的客户, 要啥?)
}
}
//购物开始了
一次购物体验.开始购物(,“锤子”)
举例总结
五金店有锤子,锤子也可能是一个Element实现,五金店也是,这个看具体实现,对于大体使用场景并不是非常重要。五金店肯定是一个Element,能接受Visitor,那么五金店里有锤子,而五金店本身并不关心访问者拿了锤子去干什么,给合格的访问者提供锤子是他的能力而已,对于锤子可以做的比如做板凳、修房子等具体事宜并不是五金店需要负责的东西,而是需要访问者自己关心的。
总结
访问者模式有些晦涩难懂,关键在于不能明确他的使用场景是什么,具体的工作中可能得以应用的地方比较少。
使用场景应该适用于那些相对非常稳定的被访问者,他们可以提供一些基础能力、基础属性,但是因为这些能力、属性可以做到的事情非常多,又不该是其本身需要面面俱到去负责的。那么这个时候就需要访问者(或者我理解也可以说成是使用者),访问者需要完成什么复杂的、多变的事情,那么被访问者(工具方)提供给你必要的资源、元素,你放手去做,只要你是个合格的访问者,符合被访问者的设想(能够响应你的参数等)即可。
又好像瑞士军刀,它提供给你各种小工具,使用者要做什么自己来决定。在程序设计中,如果存在那些比较基层的组件、工具、数据结构,在具体的业务场景中所能(组合)发挥的功能千变万化,那么访问者模式的设计思维应该是适合的。