Visitor访问者模式
In object-oriented programming and software engineering, the visitor design pattern is a way of separating an algorithm from an object structure on which it operates. A practical result of this separation is the ability to add new operations to existent object structures without modifying the structures. It is one way to follow the open/closed principle.
在面向对象的设计模式中,访问者模式是一种将某类方法从类中隔离的途径。这种隔离操作的一个好处是我们可以任意添加新的操作而不用改类的结构,这样的操作非常符合开闭原则。
实际Visitor访问者模式多用在需要遍历对象的时候,我们如果需要根据对象的类型有不同的操作,则可以将这些操作封装为Visitor类,此时,如果我们以后有别的需求,需要扩展这些操作,则可以通过extends Vistior类来进行。
我们首先看下Visitor的类图:
Visitor Pattern
从类图中我们可以看出,我们将本该处于Element中的方法逻辑提到了Visitor中,这样当我们需要逻辑扩展的时候,便可以避免修改原有的类,而直接新增Visitor即可。
对于访问者模式来讲,几乎有一个约定俗成的写法,一是具体类Element中的accept函数,一般都会写作:
public void accept(IVisitor visitor){
visitor.visit(this);
}
不过,可能多少回有些出入,比如有的时候,对于树的结构来讲,在accept中会加上遍历等操作。
我们以wiki中的例子来作为展示, 例子的Element对应的是车的部分,而Visitor模式则对应的是打印或保存各部分的内容:
interface CarElement {
void accept(CarElementVisitor visitor);
}
interface CarElementVisitor {
void visit(Body body);
void visit(Car car);
void visit(Engine engine);
void visit(Wheel wheel);
}
class Car implements CarElement {
CarElement[] elements;
public Car() {
this.elements = new CarElement[] {
new Wheel("front left"), new Wheel("front right"),
new Wheel("back left"), new Wheel("back right"),
new Body(), new Engine()
};
}
public void accept(final CarElementVisitor visitor) {
for (CarElement elem : elements) {
elem.accept(visitor);
}
visitor.visit(this);
}
}
class Body implements CarElement {
public void accept(final CarElementVisitor visitor) {
visitor.visit(this);
}
}
class Engine implements CarElement {
public void accept(final CarElementVisitor visitor) {
visitor.visit(this);
}
}
class Wheel implements CarElement {
private String name;
public Wheel(final String name) {
this.name = name;
}
public String getName() {
return name;
}
public void accept(final CarElementVisitor visitor) {
visitor.visit(this);
}
}
class CarElementDoVisitor implements CarElementVisitor {
public void visit(final Body body) {
System.out.println("Moving my body");
}
public void visit(final Car car) {
System.out.println("Starting my car");
}
public void visit(final Wheel wheel) {
System.out.println("Kicking my " + wheel.getName() + " wheel");
}
public void visit(final Engine engine) {
System.out.println("Starting my engine");
}
}
class CarElementPrintVisitor implements CarElementVisitor {
public void visit(final Body body) {
System.out.println("Visiting body");
}
public void visit(final Car car) {
System.out.println("Visiting car");
}
public void visit(final Engine engine) {
System.out.println("Visiting engine");
}
public void visit(final Wheel wheel) {
System.out.println("Visiting " + wheel.getName() + " wheel");
}
}
public class VisitorDemo {
public static void main(final String[] args) {
final Car car = new Car();
car.accept(new CarElementPrintVisitor());
car.accept(new CarElementDoVisitor());
}
}