访问者模式
应用场景 (实际问题需求) 与 传统实现方式
例如:
完成一个测评系统:
将观众分为男人和女人, 对歌手进行测评,当看完某个歌手表演后,得到他们对该歌手不同的评价(评价分不同种类,例如: 成功 失败 等)
传统实现:将评价操作直接定义在男人,女人类中。
传统实现的问题:
1. 不利于维护。
2. 扩展性不好,增加 新的人员类型 , 或者管理方法,导致改动大。
引入访问者设计模式
1. 定义
在访问者模式中, 使用一个访问者接口, 通过定义不同的访问者接口实现类,可以改变被访问者的执行操作,通过这种方式,被访问者的执行算法可以随着访问者改变而改变。此时访问者相当于被访问者可以执行(展示)出的不同种类的操作。
根据模式,被访问对象接收访问者对象(accept方法中参数是访问者对象),通过回调访问者对象中的不同方法,被访问者就可以展示出不同的操作。
这种类型的设计模式属于行为型模式。
2. 意图
主要是将数据结构和数据操作分离。
解决数据结构和操作耦合性问题。
它使你可以在不改变 被访问者类的前提下 扩展被访问者类的不同的操作。
原理类图
剖析原理 (主要角色及职责)
模式中存在的角色:
visitor:抽象访问者,为该对象结构中的ConcreteElement的每一个类声明一个visit操作。
ConcreteVisitor: 一个具体的访问者类,实现每个由Visitor声明的操作,是每个操作实现的部分。
ObjectStructure: 能枚举Element的元素, 提供一个高层的接口,用来允许访问者访问元素。
Element : 定义一个accept方法,接收一个访问者对象。
ConcreteElement: 继承或实现Element,是具体元素,实现 accept方法(调用操作)。
分析实现步骤
先确定 访问者(ConcreteVisitor) 和 被访问者(ConcreteElement) 是哪些:
1. 定义上层Visitor接口 抽象访问者,添加对ConcreteElement的每一个类不同的visit操作。
2. 定义Element 接口,定义 accept方法 表示接受访问者访问。
3. 定义不同的ConcreteVisitor类,每个类代表了不同的操作,实现Visitor 实现 visit 操作。
4. 定义不同的ConcreteElement类,每个类代表了不同的被访问者,操作调用者(接收访问)。实现Element的accept方法。
5. 定义ObjectStructure类:用于管理访问者(ConcreteVisitors)去访问被访问者(ConcreteElements),通常将被访问者放入集合中使用。
6. 定义Client类 用于访问ObjectStructure 进行测试。
代码实现
// 访问者 : 失败 和 成功(测评操作) , 被访问者 : 男人 女人 (观众)
// 定义 Visitor 抽象类 / 接口
public abstract class Action {
// 对于不同被访问者 执行 不同操作
abstract void getResult(Man man);
abstract void getResult(Woman woman);
}
// 定义 Element 抽象类 / 接口
public abstract class Person {
// 表示接受访问
abstract void accept(Action action);
}
// 定义 不同的ConcreteVisitor , 不同的ConcreteVisitor定义对于不同的ConcreteElements进行不同的操作
// 定义 success时的操作
public class Success extends Action{
// success时,对男人的操作
@Override
void getResult(Man man) {
System.out.println("man say success");
}
// success时,对女人的操作
@Override
void getResult(Woman woman) {
System.out.println("woman say success");
}
}
// 定义 Fail时的操作
public class Fail extends Action{
// Fail时,对男人的操作
@Override
void getResult(Man man) {
System.out.println("man say fail");
}
// Fail时,对女人的操作
@Override
void getResult(Woman woman) {
System.out.println("woman say fail");
}
}
// 定义被访问者 , 实现 accept 操作
// 定义 man, 实现 accept
public class Man extends Person{
// 表示接受访问者(Action), 通过访问者调用 需要执行的操作
@Override
void accept(Action action) {
action.getResult(this); // 传入 this , 通过本身数据类型,调用action中不同的getResult重载方法。
}
}
// 定义woman,实现 accept
public class Woman extends Person{
// 表示接受访问者(Action), 通过访问者调用 需要执行的操作
@Override
void accept(Action action) {
action.getResult(this);
}
}
// 定义ObjectStructure , 从高层进行访问者访问操作
public class ObjectStructure {
/**
* 维护了一个集合
*/
private List<Person> list = new ArrayList<>();
// 向集合中添加被访问者元素
public void attach(Person p) {
list.add(p);
}
// 从集合中移除被访问者元素
public void detach(Person p) {
list.remove(p);
}
// action 访问 被访问者 , 在 Client 中传入不同的访问者 , 执行不同操作
public void display(Action action) {
for (Person person : list) {
person.accept(action);
}
}
}
// 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);
// 直接添加一个 Wait(评价待定) 类 , 就可以进行不同的操作。
Wait wait = new Wait();
objectStructure.display(wait);
}
}
// 添加Wait类
public class Wait extends Action{
/**
* man的 wait评价 方法
* @param man 传入 Person子类 man
*/
@Override
void getResult(Man man) {
System.out.println("man say wait");
}
/**
* woman的 wait评价方法
* @param woman 传入Person子类 woman
*/
@Override
void getResult(Woman woman) {
System.out.println("woman say wait");
}
}
总结
标签:定义,void,模式,accept,操作,public,访问者 From: https://www.cnblogs.com/oneblogs/p/17181734.html访问者模式主要应用场景:需要对一个(Elements)对象结构中的对象进行很多不同类型操作(这些操作彼此没有关联),同时需要避免让 这些频繁修改增添的操作 直接写在这些类中,可以使用访问者模式。