一、模式动机
对于系统中的某些对象,它们存储在同一个集合中,且具有不同的类型,而且对于该集合中的对象,可以接受一类称为访问者的对象来访问,而且不同的访问者其访问方式有所不同,访问者模式为解决这类问题而诞生。
在实际使用时,对同一集合对象的操作并不是唯一的,对相同的元素对象可能存在多种不同的操作方式。
而且这些操作方式并不稳定,可能还需要增加新的操作,以满足新的业务需求。
二、模式定义
访问者模式(Visitor Pattern):表示一个作用于某对象结构中的各元素的操作。它使我们可以在不改变各元素的类的前提下定义作用于这些元素的新操作。访问者模式是一种对象行为型模式。
三、模式结构
四、参与者
- Vistor:抽象访问者
- ConcreteVisitor:具体访问者
- Element:抽象元素
- ConcreteElement:具体元素
- ObjectStructure:对象结构
五、示例代码
package design.pattern;
import java.util.ArrayList;
abstract class Element {
public abstract void accept(Visitor visitor);
}
class ConcreteElementA extends Element {
public void accept(Visitor visitor) {
visitor.visitElement(this);
}
public void operationA() {
}
}
class ConcreteElementB extends Element {
public void accept(Visitor visitor) {
visitor.visitElement(this);
}
public void operationB() {
}
}
class ObjectStructure {
private ArrayList<Element> elements = new ArrayList<>();
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);
}
}
}
public abstract class Visitor {
public void visitElement(Element element) {
System.out.println(element.getClass().getName() + " visited by " + this.getClass().getName());
}
public static void main(String[] args) {
ObjectStructure o = new ObjectStructure();
o.attach(new ConcreteElementA());
o.attach(new ConcreteElementB());
ConcreteVisitorA v1 = new ConcreteVisitorA();
ConcreteVisitorB v2 = new ConcreteVisitorB();
o.accept(v1);
o.accept(v2);
}
}
class ConcreteVisitorA extends Visitor {
}
class ConcreteVisitorB extends Visitor {
}
模式结构
优点
- 访问者模式使得增加新的操作变得很容易。如果一些操作依赖于一个复杂的结构对象的话,那么一般而言,增加新的操作会很复杂。而使用访问者模式,增加新的操作就意味着增加一个新的访问者类,因此将变得很容易。
- 访问者模式将有关的行为集中到一个访问者对象中,而不是分散到一个个的节点类中。
- 访问者模式可以跨过几个类的等级结构访问属于不同的等级结构的成员类。
缺点
- 破坏封装。访问者模式要求访问者对象访问并调用每一个节点对象的操作,这隐含了一个对所有节点对象的要求:它们必须暴露一些自己的操作和内部状态。不然,访问者的访问就变得没有意义。由于访问者对象自己会积累访问操作所需的状态,从而使这些状态不再存储在节点对象中,这也是破坏封装的。
- 增加新的节点类变得很困难。每增加一个新的节点都意味着要在抽象访问者角色中增加一个新的抽象操作,并在每一个具体访问者类中增加相应的具体操作。
模式使用
- 定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。
- 对象需要添加很多不同的并且不相关的操作,而我们想避免让这些操作“污染”这些对象的类。访问者模式使得我们可以将相关的操作集中起来定义在一个类中。当该对象结构被很多应用共享时,用访问者模式让每个应用仅包含需要用到的操作。
模式应用
- 访问者模式中对象结构存储了不同类型的元素对象,以供不同访问者访问。访问者模式包括两个层次结构,一个是访问者层次结构,提供了抽象访问者和具体访问者,一个是元素层次结构,提供了抽象元素和具体元素。相同的访问者可以以不同的方式访问不同的元素,相同的元素可以接受不同访问者以不同访问方式访问。
- 在访问者模式中,增加新的访问者无须修改原有系统,系统具有较好的可扩展性。
模式小结
访问者模式的主要优点在于使得增加新的访问操作变得很容易,将有关元素对象的访问行为集中到一个访问者对象中,而不是分散到一个个的元素类中,还可以跨过类的等级结构访问属于不同的等级结构的元素类,让用户能够在不修改现有类层次结构的情况下,定义该类层次结构的操作;其主要缺点在于增加新的元素类很困难,而且在一定程度上破坏系统的封装性。