访问者模式
访问者模式是一种将算法与对象结构分离的软件设计模式。它可以让你在不修改对象结构的情况下,对对象结构中的元素进行不同的操作。访问者模式的优点是符合单一职责原则,优秀的扩展性和灵活性。缺点是具体元素对访问者公布细节,违反了迪米特原则,而且如果元素类经常变化,会导致访问者类需要频繁修改。
访问者模式适合在以下场景下使用:
- 对象结构比较稳定,但经常需要在此对象结构上定义新的操作。
- 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作“污染”这些对象的类,也不希望在增加新操作时修改这些类。
- 对象结构中的元素类型很少变化,但每个元素都有很多种变化的可能性,并且每一种变化都影响到元素的行为。
一个访问者模式的例子。
这个例子中,有一个计算机组件的接口(ComputerPart),它有一个accept方法用来接受访问者对象(ComputerPartVisitor)。
然后有三个实现了这个接口的类:键盘(Keyboard),鼠标(Mouse)和显示器(Monitor)。
每个类都实现了accept方法,调用访问者对象的visit方法,并传递自身作为参数。
访问者对象是一个接口,它有三个visit方法,分别对应三种不同的计算机组件。然后有两个实现了这个接口的类:计算机显示访问者(ComputerDisplayVisitor)和计算机修理访问者(ComputerRepairVisitor)。
每个类都实现了三个visit方法,分别对不同的计算机组件执行不同的操作。
最后,有一个计算机类(Computer),它包含了三种计算机组件,并且也实现了accept方法,调用每个组件的accept方法,并传递自身作为参数。下面是部分代码:
// 计算机组件接口 public interface ComputerPart { public void accept(ComputerPartVisitor computerPartVisitor); } // 键盘类 public class Keyboard implements ComputerPart { @Override public void accept(ComputerPartVisitor computerPartVisitor) { computerPartVisitor.visit(this); } } // 鼠标类 public class Mouse implements ComputerPart { @Override public void accept(ComputerPartVisitor computerPartVisitor) { computerPartVisitor.visit(this); } } // 显示器类 public class Monitor implements ComputerPart { @Override public void accept(ComputerPartVisitor computerPartVisitor) { computerPartVisitor.visit(this); } } // 访问者接口 public interface ComputerPartVisitor { public void visit(Keyboard keyboard); public void visit(Mouse mouse); public void visit(Monitor monitor); } // 计算机显示访问者类 public class ComputerDisplayVisitor implements ComputerPartVisitor { @Override public void visit(Keyboard keyboard) { System.out.println("Displaying Keyboard."); } @Override public void visit(Mouse mouse) { System.out.println("Displaying Mouse."); } @Override public void visit(Monitor monitor) { System.out.println("Displaying Monitor."); } } // 计算机修理访问者类 public class ComputerRepairVisitor implements ComputerPartVisitor { @Override public void visit(Keyboard keyboard) { System.out.println("Repairing Keyboard."); } @Override public void visit(Mouse mouse) { System.out.println("Repairing Mouse."); } @Override public void visit(Monitor monitor) { System.out.println("Repairing Monitor."); } } // 计算机类 public class Computer implements ComputerPart { private final List<ComputerComponent> components; // 构造函数初始化键盘、鼠标和显示器 // 实现accept方法 // 调用每个组件的accept方法,并传递自身作为参数 }
这段代码的目的是演示访问者模式的用法,它定义了一个计算机组件的接口,和三个实现了这个接口的类,分别代表键盘、鼠标和显示器。这些类都有一个accept方法,用来接受一个访问者对象,并调用它的visit方法。访问者对象是一个接口,它有三个visit方法,分别对应三种不同的计算机组件。这个接口有两个实现类,分别是计算机显示访问者和计算机修理访问者。这两个类都实现了三个visit方法,分别对不同的计算机组件执行不同的操作。例如,计算机显示访问者会打印出每个组件的名称,而计算机修理访问者会打印出每个组件正在被修理。最后,有一个计算机类,它包含了三种计算机组件,并且也实现了accept方法。当调用这个方法时,它会遍历所有的组件,并调用它们的accept方法,并传递自身作为参数。这样就可以根据不同的访问者对象,在不修改原有类结构和行为的情况下,对每个组件执行不同的操作。
假设我们创建了一个计算机对象,然后分别用计算机显示访问者和计算机修理访问者来访问它,那么运行结果可能是这样的:
// 创建一个计算机对象 Computer computer = new Computer(); // 创建一个计算机显示访问者对象 ComputerDisplayVisitor displayVisitor = new ComputerDisplayVisitor(); // 调用计算机的accept方法,并传递显示访问者对象 computer.accept(displayVisitor); // 输出结果: Displaying Keyboard. Displaying Mouse. Displaying Monitor. // 创建一个计算机修理访问者对象 ComputerRepairVisitor repairVisitor = new ComputerRepairVisitor(); // 调用计算机的accept方法,并传递修理访问者对象 computer.accept(repairVisitor); // 输出结果: Repairing Keyboard. Repairing Mouse. Repairing Monitor.