0%

设计模式-访问者模式

表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作。

访问者模式适用于数据结构相对稳定的系统,它解耦了数据结构(元素类)和作用于结构上的操作(访问者类),使得操作集合可以相对自由地演化。访问者模式把处理从数据结构中分离出来,对于有稳定的数据结构,又有易于变化的算法的场景,使用访问者模式比较合适。

访问者模式的优点是增加新的操作很容易,因为增加新的操作就意味着增加一个新的访问者,访问者模式将有关的行为集中到一个访问者对象中。

类图

  • Visitor:抽象访问者,为每一个 ConcreteElement 声明一个 visit 操作,使得可以访问每一个 ConcreteElement 。
  • ConcreteVisitor:具体访问者,实现每个由 Visitor 声明的操作,每个操作实现算法的一部分,而该算法片段作用于 ObjectStructure 中的元素。
  • ObjectStructure:对象结构,可以是组合结构,或者是一个集合,能枚举它的元素,可以提供一个高层的接口允许访问者访问它的元素。
  • Element:被访问的元素。

3YZj2t.md.png

实现

1
2
3
4
5
6
7
public abstract class Visitor {

public abstract void visit(ConcreteElementA concreteElementA);

public abstract void visit(ConcreteElementB concreteElementB);

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class ConcreteVisitorA extends Visitor {

@Override
public void visit(ConcreteElementA concreteElementA) {
System.out.println(
String.format("%s被%s访问", concreteElementA.getClass().getSimpleName(), this.getClass().getSimpleName()));
}

@Override
public void visit(ConcreteElementB concreteElementB) {
System.out.println(
String.format("%s被%s访问", concreteElementB.getClass().getSimpleName(), this.getClass().getSimpleName()));
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class ConcreteVisitorB extends Visitor {

@Override
public void visit(ConcreteElementA concreteElementA) {
System.out.println(
String.format("%s被%s访问", concreteElementA.getClass().getSimpleName(), this.getClass().getSimpleName()));
}

@Override
public void visit(ConcreteElementB concreteElementB) {
System.out.println(
String.format("%s被%s访问", concreteElementB.getClass().getSimpleName(), this.getClass().getSimpleName()));
}

}
1
2
3
4
5
public abstract class Element {

public abstract void accept(Visitor visitor);

}
1
2
3
4
5
6
7
8
9
10
11
12
public class ConcreteElementA extends Element {

@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}

public void operationA() {

}

}
1
2
3
4
5
6
7
8
9
10
11
12
public class ConcreteElementB extends Element {

@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}

public void operationB() {

}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class ObjectStructure {

private List<Element> elements = new ArrayList<Element>();

public void attach(Element element) {
elements.add(element);
}

public void detach(Element element) {
elements.remove(element);
}

public void accept(Visitor visitor) {
for (Element e : elements) {
e.accept(visitor);
}
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Client {

public static void main(String[] args) {
ObjectStructure os = new ObjectStructure();
os.attach(new ConcreteElementA());
os.attach(new ConcreteElementB());

ConcreteVisitorA v1 = new ConcreteVisitorA();
ConcreteVisitorB v2 = new ConcreteVisitorB();

os.accept(v1);
os.accept(v2);
}

}