访问者模式
定义:将作用于某种数据结构中的各元素的操作分离出来封装为独立的类,使其在不改变数据结构的前提下可以添加作用于这些元素的新的操作,为数据结构中的每个元素提供多种访问方式。
使用场景:
- 对象结构很少改变,但是需要经常在结构上定义新的操作。
- 需要对一个对象结构中的对象进行很多不同并且不相关的操作,避免新增操作的时候修改这些类。
结构:
- 抽象访问者(Visitor):定义一个访问具体元素的接口
- 具体访问者(ConcreteVisitor): 实现抽象访问者中的接口
- 抽象元素(Element) :声明一个包含操作accept()的接口,被接受的访问者对象作为accept()方法的参数。
- 具体元素(ConcreteElement):实现抽象元素角色提供的accept()操作,其方法通常都是visitor.visit(this),另外具体元素中可能还包含本身业务逻辑的操作。
- 对象结构(ObjectStructure):是一个包含元素角色的容器,提供让访问者对象遍历容器中的所有元素的方法。
举例场景:有一个房子,不同的租客来看房,对于房子的各个部分需要进行的操作(查看的地方)不同,但是房子的结构是固定的(卧室、厨房、卫生间)。示例代码如下:
public interface Element {
void accept(Visitor visitor);
}
public class BedRoomElement implements Element {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
public class KitchenElement implements Element {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
public class ToiletElement implements Element {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
//相当于对象结构类
public class House {
private List<Element> list=new ArrayList<>();
public void add(Element element){
list.add(element);
}
public void accept(Visitor visitor){
list.forEach(e->e.accept(visitor));
}
}
public interface Visitor {
void visit(BedRoomElement bedRoomElement);
void visit(KitchenElement kitchenElement);
void visit(ToiletElement toiletElement);
}
public class ConcreteVisitorA implements Visitor {
@Override
public void visit(BedRoomElement bedRoomElement) {
System.out.println("查看卧室采光");
}
@Override
public void visit(KitchenElement kitchenElement) {
System.out.println("查看厨房卫生");
}
@Override
public void visit(ToiletElement toiletElement) {
System.out.println("查看卫生间漏水");
}
}
public class ConcreteVisitorB implements Visitor {
@Override
public void visit(BedRoomElement bedRoomElement) {
System.out.println("查看卧室朝向");
}
@Override
public void visit(KitchenElement kitchenElement) {
System.out.println("查看厨房大小");
}
@Override
public void visit(ToiletElement toiletElement) {
System.out.println("查看卫生间卫生");
}
}
测试代码:
public static void main(String[] args) throws InterruptedException, CloneNotSupportedException {
House house=new House();
house.add(new BedRoomElement());
house.add(new KitchenElement());
house.add(new ToiletElement());
//租客A看房
Visitor visitor=new ConcreteVisitorA();
house.accept(visitor);
//租客B看房
Visitor visitorB=new ConcreteVisitorB();
house.accept(visitorB);
}