语言与模式-22访问者模式
意图
表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
适用性
- 一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操作。
- 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而你想避免让这些操作“污染”这些对象的类。Visitor使得你可以将相关的操作集中起来定义在一个类中。当该对象结构被很多应用共享时,用Visitor模式让每个应用仅包含需要用到的操作。
- 定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。改变对象结构类需要重定义对所有访问者的接口,这可能需要很大的代价。如果对象结构类经常改变,那么可能还是在这些类中定义这些操作较好。
Java实现
//访问者
public interface Visitor {
public void visit(Park park);
public void visit(ParkA parkA);
public void visit(ParkB parkB);
}
//清洁工A,负责parkA的卫生情况
public class VisitorA implements Visitor {
public void visit(Park park) {
}
public void visit(ParkA parkA) {
System.out.println("清洁工A:完成公园" + parkA.getName()+ "的卫生");
}
public void visit(ParkB parkB) {
}
}
//清洁工B,负责公园B部分的卫生
public class VisitorB implements Visitor {
public void visit(Park park) {
}
public void visit(ParkA parkA) {
}
public void visit(ParkB parkB) {
System.out.println("清洁工B:完成公园" + parkB.getName()+"的卫生");
}
}
public class VisitorManager implements Visitor {
public void visit(Park park) {
System.out.println("管理员:负责" + park.getName() + "卫生检查");
}
public void visit(ParkA parkA) {
System.out.println("管理员:负责公园"+ parkA.getName() +"部分卫生检查");
}
public void visit(ParkB parkB) {
System.out.println("管理员:负责公园"+ parkB.getName() +"分部卫生检查");
}
}
//公园每一部分的抽象
public interface ParkElement {
//用来接纳访问者
public void accept(Visitor visitor);
}
public class Park implements ParkElement {
private String name;
private ParkA parkA;
private ParkB parkB;
public Park() {
this.parkA = new ParkA();
this.parkB = new ParkB();
parkA.setName("A");
parkB.setName("B");
}
public void accept(Visitor visitor) {
visitor.visit(this);
parkA.accept(visitor);
parkB.accept(visitor);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//公园的A部分
public class ParkA implements ParkElement {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
//公园的B部分
public class ParkB implements ParkElement{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
public class MainClass {
public static void main(String[] args) {
Park park = new Park();
park.setName("锦绣公园");
VisitorA visitorA = new VisitorA();
park.accept(visitorA);
VisitorB visitorB = new VisitorB();
park.accept(visitorB);
VisitorManager visitorManager = new VisitorManager();
park.accept(visitorManager);
}
}
Clojure实现
访问者模式干了什么呢?我自己(这里是Park)有个结构,我委托给其他对象(Visitor)来实现访问逻辑!
Clojure没有类似的结构体!比如复杂的树结构,可以使用Clojure提供的数据操作函数来进行操作即可!没必要实现个模式!