定义
访问者(Visitor)模式是一种对象行为型模式,将作用于某种数据结构中的各元素的操作分离出来封装成独立的类,使其在不改变数据结构的前提下可以添加作用于这些元素的新的操作,为数据结构中的每个元素提供多种访问方式。它将对数据的操作与数据结构进行分离。
应用场景
稳定的数据结构和易变的操作耦合问题。就是把数据结构和作用于结构上的操作解耦合,使得操作集合可相对自由地演化。
访问者模式结构
- 抽象访问者(Visitor)角色:定义一个访问具体元素的接口,为每个具体元素类对应一个访问操作 visit() ,该操作中的参数类型标识了被访问的具体元素。
- 具体访问者(ConcreteVisitor)角色:实现抽象访问者角色中声明的各个访问操作,确定访问者访问一个元素时该做什么。
- 抽象元素(Element)角色:声明一个包含接受操作 accept() 的接口,被接受的访问者对象作为 accept() 方法的参数。
- 具体元素(ConcreteElement)角色:实现抽象元素角色提供的 accept() 操作,其方法体通常都是 visitor.visit(this) ,另外具体元素中可能还包含本身业务逻辑的相关操作。
- 对象结构(Object Structure)角色:是一个包含元素角色的容器,提供让访问者对象遍历容器中的所有元素的方法,通常由 List、Set、Map 等聚合类实现。
代码示例
//有一个公园,公园里有假山和湖
public interface ParkElement {
public void accept(Visitor visitor);
}
public class LakeElement implements ParkElement {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
public String lake() {
return "活水";
}
public String lakeArea() {
return "3000平米";
}
}
public class RockeryElement implements ParkElement {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
public String high() {
return "800米高";
}
public String makeUp() {
return "石头山";
}
}
public class ParStructure {
List<ParkElement> parkElementList = new ArrayList<ParkElement>();
public ParStructure() {
parkElementList.add(new LakeElement());
parkElementList.add(new RockeryElement());
}
public void guangyiguang(Visitor visitor) {
parkElementList.forEach(a -> {
a.accept(visitor);
});
}
public static void main(String[] args) {
AVistor aVistor = new AVistor();
BVistor bVistor = new BVistor();
ParStructure parStructure = new ParStructure();
parStructure.guangyiguang(aVistor);
parStructure.guangyiguang(bVistor);
}
}
//游客A和游客B
public interface Visitor {
void visit(LakeElement lakeElement);
void visit(RockeryElement rockeryElement);
}
public class AVistor implements Visitor {
@Override
public void visit(LakeElement lakeElement) {
System.out.println("A游客关注湖死水活水===" + lakeElement.lake());
}
@Override
public void visit(RockeryElement rockeryElement) {
System.out.println("A游客关注是个什么山===" + rockeryElement.makeUp());
}
}
public class BVistor implements Visitor {
@Override
public void visit(LakeElement lakeElement) {
System.out.println("B游客关注湖有多大===" + lakeElement.lakeArea());
}
@Override
public void visit(RockeryElement rockeryElement) {
System.out.println("B游客关注山高===" + rockeryElement.high());
}
}
//A和B逛公园输出:
A游客关注湖死水活水===活水
A游客关注是个什么山===石头山
B游客关注湖有多大===3000平米
B游客关注山高===800米高
公园里的元素是固定的,每个人游玩都有自己的关注点。游客和公园的元素解耦。