访问者模式
访问者模式(Visitor Pattern)是属于行为模式,它封装了一些用于某种数据结构的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些操作的新操作。
访问者模式的基本原理是:在被访问的类里加一个对外提供接待访问者的接口。主要将数据结构与数据分离,解决数据结构和操作耦合性的问题。
访问者模式主要应用场景是:需要对一个对象结构中的对象进行很多不同操作(这些操作彼此没有关联),同时需要避免让这些操作"污染"这些对象的类,可以选用访问者模式解决。
观察模式的五个角色
- Visitor(抽象访问者):抽象访问者为对象结构中每一个具体元素类
ConcreteElement
声明一个访问操作,从这个操作的名称或参数类型可以清楚知道需要访问的具体元素的类型,具体访问者则需要实现这些操作方法,定义对这些元素的访问操作。 - ConcreteVisitor(具体访问者):具体访问者实现了抽象访问者声明的方法,每一个操作作用于访问对象结构中一种类型的元素。
- Element(抽象元素):一般是一个抽象类或接口,定义一个Accept方法,该方法通常以一个抽象访问者作为参数。
- ConcreteElement(具体元素):具体元素实现了Accept方法,在Accept方法中调用访问者的访问方法以便完成一个元素的操作。
- ObjectStructure(对象结构):对象结构是一个元素的集合,用于存放元素对象,且提供便利其内部元素的方法。
![](https://tva1.sinaimg.cn/large/007S8ZIlly1gj6rtv6pxgj30q10peaay.jpg)
举一个栗子
将人分为男人和女人,对歌手进行测评,当看完某个歌手表演后,通过得到他们对该歌手不同的分数来得到一个评价,评价有成功和失败(分数大于 60 为成功,分数小于 60 为失败)。
类图:
![image-20200928232119070](https://tva1.sinaimg.cn/large/007S8ZIlly1gj6s08chgtj30uo0tsmz1.jpg)
Visitor:抽象访问者
抽象访问者为对象结构体中的具体元素对象声明了一个访问操作的接口。
package cn.personalweb.visitor;
public interface Visitor {
void visit(Man man);
void visit(Woman woman);
}
Element:抽象元素
package cn.personalweb.visitor;
public interface Element {
/**
* 提供一个方法,接受访问者对象,让访问者可以访问
* @param visitor 访问者对象
*/
void accept(Visitor visitor);
}
Man:具体元素 男人
具体元素中的accept()
方法采用了双分派,首先在客户端程序中,将具体状态作为参数传递给Man
(第一次分派),然后Man
类调用做为参数中的“具体方法”中的visit()
,同时将自己this
作为参数传入(第二次分派)。
所谓双分派是指不管类怎么变化,我们都能找到期望的方法运行。双分派意味着得到执 行的操作取决于请求的种类和两个接收者的类型
package cn.personalweb.visitor;
public class Man implements Element{
private String name;
private int score;
public Man(String name, int score) {
this.name = name;
this.score = score;
}
@Override
public void accept(Visitor visitor) {
visitor.visit