1. 访问者模式概述
在访问者模式中,我们使用了一个访问者类,它改变了元素类的执行算法。
通过这种方式,元素的执行算法可以随着访问者改变而改变。
根据模式,元素对象已接受访问者对象,这样访问者对象就可以处理元素对象上的操作。
访问者模式不好理解,建议直接看例子。
(1) 适用情况
主要将数据结构与数据操作分离,适用于稳定的数据结构和易变的操作耦合的情况。
(2) 优点
方便拓展、灵活,符合单一职责原则。
(3) 缺点
具体元素对访问者公布细节,违反了迪米特原则。具体元素变更比较困难。违反了依赖倒置原则,依赖了具体类,没有依赖抽象。
2. 访问者模式实例
主人买了个大房子,里面有好多个小房间,客人使用访问者模式来实现对大房子和各个房间的访问。 (1) 定义了房间接口
public interface Room {
void accept(Visitor visitor);
}
(2) 实现各个房间类
public class Parlor implements Room {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
public class Kitchen implements Room {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
public class Bedroom implements Room {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
(3) 实现大房子类
public class House implements Room {
Room[] rooms;
public House() {
rooms = new Room[]{new Parlor(), new Kitchen(), new Bedroom()};
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
for (Room part : rooms) {
part.accept(visitor);
}
}
}
(4) 实现访问者类
public class Visitor {
public void visit(House house) {
System.out.println("好漂亮的房子!");
}
public void visit(Parlor parlor) {
System.out.println("好宽敞的客厅!");
}
public void visit(Kitchen kitchen) {
System.out.println("好整洁的厨房!");
}
public void visit(Bedroom bedroom) {
System.out.println("好温馨的卧室!");
}
}
(6) 使用访问者模式
public class VisitorDemo {
public static void main(String[] args) {
House house = new House();
house.accept(new Visitor());
}
}
运行结果:
3. 一些思考
访问者模式应该是23种经典设计模式中最难理解和掌握的了,SQL解析器中就大量的使用了访问者模式。
思考上述代码,我们看最后调用的方式:
house.accept(new Visitor());
可以这么来理解这行代码:house对象接受了一个访问者,这个访问者是Visitor类的一个实例
house就是主人的大房子,他可以允许客人来访问自己,但是是由主人来决定客人什么时候访问、怎么访问。这就是accept方法的实现。
visitor就是一个客人,它要访问主人的大房子,心里就必须先想好他要怎么访问。这就是visit方法的实现。