1、定义
表示一个作用于某对象结构中的各元素操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
2、使用场景
男人成功时,背后多半有一个伟大的女人;
女人成功时,背后多半有一个不成功的男人;
男人失败时,闷头喝酒,谁也不用劝;
女人失败时,眼泪汪汪,谁也劝不了;
男人恋爱时,凡事不懂也要装懂;
女人恋爱时,遇事懂也装作不懂。
以上仅是书中的观点,不代表博主。
3、代码结构UML图
状态:为该对象结构中ConcreteElement的每一个类声明一个Visit操作。
成功、失败:具体访问者,实现每个有Visitor声明的操作。每个操作实现算法的一部分,而该算法片段仍是对应于结构中对象的类 。
对象结构:能枚举它的元素,可以提供一个高层的接口以允许访问者访问它的元素。
人:定义一个Accept操作,它以一个访问者作为参数。
男人、女人:具体元素,实现Accept操作
4、类的实现
(1)Action (状态的抽象类 和 人的抽象类)
public abstract class Action {
//得到男人结论或反应
public abstract void getManConclusion(Man currentElementA);
//得到女人结论或反应
public abstract void getWomanConclusion(Woman currentElementB);
}
(2)Success、Faling、Amativeness(具体状态 类)
public class Success extends Action {
@Override
public void getManConclusion(Man currentElementA) {
System.out.println(currentElementA.getClass().getSimpleName() +" "+this.getClass().getSimpleName()+"时,背后多半有一个伟大的女人。");
}
@Override
public void getWomanConclusion(Woman currentElementB) {
System.out.println(currentElementB.getClass().getSimpleName() +" "+this.getClass().getSimpleName()+"时,背后大多有一个不成功的男人。");
}
}
public class Failing extends Action {
@Override
public void getManConclusion(Man currentElementA) {
System.out.println(currentElementA.getClass().getSimpleName() +" "+ this.getClass().getSimpleName() + "时,闷头喝酒,谁也不用劝。");
}
@Override
public void getWomanConclusion(Woman currentElementB) {
System.out.println(currentElementB.getClass().getSimpleName() +" " + this.getClass().getSimpleName() + "时,眼泪汪汪,谁也劝不了。");
}
}
public class Amativeness extends Action {
@Override
public void getManConclusion(Man currentElementA) {
System.out.println(currentElementA.getClass().getSimpleName() +" "+this.getClass().getSimpleName()+"时,凡事不懂也要装懂。");
}
@Override
public void getWomanConclusion(Woman currentElementB) {
System.out.println(currentElementB.getClass().getSimpleName() +" "+this.getClass().getSimpleName()+"时,遇事懂也装作不懂。");
}
}
(3)Man、woman(男人类、女人类)
public class Man extends Person {
@Override
public void accept(Action visitor) {
//首先在程序中将具体状态作为参数传递给Men类完成一次分派,然后Men类调用作为参数的具体状态中的方法男人的反应,同时将自己(this)作为参数传递进去,这便完成了第二次分派。
visitor.getManConclusion(this);
}
}
public class Woman extends Person {
@Override
public void accept(Action visitor) {
visitor.getWomanConclusion(this);
}
}
(4)ObjectStructure(对象结构)
public class ObjectStructure {
private List<Person> elements = new ArrayList<>();
//添加
public void attach(Person person) {
elements.add(person);
}
//移除
public void remove(Person person) {
elements.remove(person);
}
//查看显示
public void display(Action visitor) {
for (Person e : elements) {
e.accept(visitor);
}
}
}
5、客户端调用
public static void main(String[] args) {
ObjectStructure objectStructure = new ObjectStructure();
objectStructure.attach(new Man());
objectStructure.attach(new Woman());
//成功时的反应
Success success = new Success();
objectStructure.display(success);
//失败时的反应
Failing failing = new Failing();
objectStructure.display(failing);
//恋爱时的反应
Amativeness amativeness = new Amativeness();
objectStructure.display(amativeness);
}
6、总结
访问者的目的是要把处理从数据结构分离出来。很多系统可以按照算法和数据机构分开,如果这样的系统有比较稳定的数据结构,又有易于变化的算法的话,使用访问者模式就是比较适合的,因为访问者模式使得算法操作的增加变得容易。反之,如果这样的系统的数据结构对象易于变化,经常要有新的数据对象新增进来,就不太适合使用访问者模式。
访问者的优点就是增加新的操作很容易,因为增加新的操作就意味着增加一个新的访问者,访问者模式将有关的行为集中到一个访问者对象中。
访问者的缺点其实也就是使增加新的数据结构变得困难了。
参考:《大话设计模式》