1. 定义
访问者模式( Visitor):表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作
2. 使用前提
这个模式是很复杂的模式,一般情况下是用不上的,但是如果需要用那就是真的要用了
虽然蛮复杂,但也挺有意思的
首先,使用访问者模式的前提是,数据结构必须稳定的,不能更改,否则这个模式就需要修改很多类,违反了开放-封闭原则,原因是在访问者类(这个类是用来写具体逻辑或者说算法的类)里面,有针对数据结构的类实现的所有方法,如果数据结构相关类改变了,那么访问者类及其继承者都要变化
比方说,人类只有两个性别(不考虑变性以及具有医学争议的性别),男性和女性,那么男性和女性就是稳定的数据结构,是不会变化的,而访问者抽象类就必须有两个方法,即针对男性的方法(FocusonMen)以及针对女性的方法(FocusonWomen),刚好一个方法对应男性(里面写针对男性所需要的逻辑),一个方法对应女性(里面写针对女性所需要的逻辑),数据结构稳定所以其访问者实现的两个方法也是稳定的
访问者模式的目的,是要把处理从数据结构分离出来。很多系统可以按照算法和数据结构分开,如果这样的系统有比较稳定的数据结构,又有易于变化的算法的话,使用访问者模式就是比较合适的,因为访问者模式使得算法操作的增加变得容易。反之,如果这样的系统的数据结构对象易于变化,经常要有新的数据对象增加进来,就不适合使用访问者模式
那其实访问者模式的优点就是增加新的操作很容易,因为增加新的操作就意味着增加一个新的访问者。访问者模式将有关的行为集中到一个访问者对象中
3. 访问者模式结构图与代码模板
结构图:
模板代码:
4. 举例与分析
题目:
针对人类的男性和女性,用访问者模式的思想,实现下面的话:
男人成功时,背后多半有一个伟大的女人。女人成功时,背后大多有一个不成功的男人。
男人失败时,闷头喝酒,谁也不用劝。女人失败时,眼泪汪汪,谁也劝不了。
男人恋爱时,凡事不懂也要装懂。女人恋爱时,遇事懂也装作不懂。
分析题目:
- 人类的男性和女性是不会变化的,人类只有男性和女性,符合使用访问者模式的前提
- 分析这些话,会发现除了男人女人外,还有其“成功”、“失败、“恋爱”三种状态,这些状态男性女性都有,可以当做访问者模式里的访问者类处理
- 另外,这些话里面还有着最终结果,即“背后多半有个成功的女人”等,可以当做是访问者类的内部逻辑是打印这句话
- 我们发现这些话是有顺序的,男性后就是女性,所以我们可以构造一个对象结构类,里面一次调用其男女方法(可以当做算法的顺序来理解)
结构图:
代码:
- 构建抽象人类
abstract class Person
{
public abstract void Apply(State state);//与状态联系起来,即与访问者联系起来
}
- 继承于抽象人类的具体性别,男性、女性
//男性
class Men : Person
{
public override void Apply(State state)
{
state.GetMenState(this)