本文已参与「掘力星计划」,赢取创作大礼包,挑战创作激励金。
小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
定义
主要将数据结构与数据操作分离。
UML图
下面就以人类分为男人和女人这个例子来实现访问者模式。UML图如下:
1. Action
抽象的状态类,主要声明以下两个方法。
这里的关键在于人只分男人和女人,这个性别的分类是稳定的,所以可以在状态类中,增加“男人反应”和“女人反应”两个方法,方法个数是稳定的,不会容易发生变化。
public abstract class Action {
//得到男人的结论或反应
public abstract void getManConclusion(Man man);
//得到女人的结论或反应
public abstract void getWomanConclusion(Woman woman);
}
复制代码
2. Person
人的抽象类。只有一个“接受”的抽象方法,它是用来获得“状态”对象的。
public abstract class Person {
//接受
public abstract void accept(Action action);
}
复制代码
3. Action类的具体实现类
这里以成功类(Success)为例,失败类(Fail)同理。
public class Success extends Action {
@Override
public void getManConclusion(Man man) {
System.out.println("男人成功...");
}
@Override
public void getWomanConclusion(Woman woman) {
System.out.println("女人成功...");
}
}
复制代码
4. Person类的具体实现类
这里以男人类(Man)为例,女人类(Woman)同理。
这里用到了双分派,即首先在客户程序中将具体状态作为参数传递给Man类完成了一次分派,然后Man类调用作为参数的“具体方法”中的方法getManConclusion(),同时将自己(this)作为参数传递进去,这便完成了第二次分派。accept方法就是一个双分派操作,它得到执行的操作不仅决定于Action类的具体状态,还决定于它访问的Person的类别。
public class Man extends Person {
@Override
public void accept(Action action) {
action.getManConclusion(this);
}
}
复制代码
5. 结构对象
public class ObjectStructure {
private List<Person> elements = new LinkedList<>();
//增加
public void attach(Person person) {
elements.add(person);
}
//移除
public void detach(Person person) {
elements.remove(person);
}
//查看显示
public void display(Action action) {
for (Person person : elements) {
person.accept(action);
}
}
}
复制代码
6. Client客户端
public class Client {
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);
}
}
复制代码