背景
做一个对歌手的评价系统,观众分为男人和女人,分别对歌手做出自己的评价。
传统思路:
做一个person父类,Man 和 Woman分别继承自这个父类,在这两个类中执行各自操作。
问题:
可拓展性差,牵一发而动全身,不符合开闭原则。
基本介绍
将数据结构和数据操作分离,解决数据结构和操作耦合性的问题。
基本工作原理是:在被访问的类里加一个对外提供接待访问者的接口。
五个角色
①Vistor:抽象访问者父类,声明visit操作方法。
②ConcreteVistor:继承自Vistor抽象父类。实现父类方法
③Element:抽象父类,可以接收一个访问者对象
④ConcreteElement:继承自Element抽象父类,实现父类方法
⑤ObjectStructure:能枚举它的元素,可以提供一个高层接口,用来使用访问者。
具体实现
创建一个Action抽象类作为访问者
创建Success和Fail作为具体访问者类。
创建一个Person抽象类作为Element类
创建Man和Woman作为具体Elemen类。
创建ObjectStructure,用于存放所有的Person类
在Action类中声明GetManResult(Man man)和GetWomanResult(Woman woman)两个抽象方法。
Success和Fail分别继承Action类,并具体实现这两个抽象方法。
在Person类中声明使用Action类的抽象方法Accept(Action action),
Man和Woman中分别调用自己对应的Action的方法GetManResult或者GetWomanResult,并把自己传入。
ObjectStructure中声明一个Person的集合,为这个集合声明增加和删除的方法。
再声明这个集合所有人都执行Accep的方法,传入Action类即可执行。
在使用时,声明ObjectStructure类,为里面增加人(Man或Woman)
可以调用ObjectStructure类中的执行方法,传入Success或者Fail就可以让ObjectStructure类中的无论男人还是女人都执行Success或是Fail。
双分派
第一次分派:在使用Person类时将具体的Action对象传入Person的方法中。
第二次分派:在Person的这个方法中使用GetManResult或者GetWomanResult又把自己作为参数传入
可以很好的解耦合
举个例子,
如果要加一个Wait类继承自Action类,实现GetManResult和GetWomanResult,
并不需要更改其他的代码,直接在调用端调用即可