Visitor, UML class diagram.
访问者模式是一种将算法与对象结构分离的软件设计模式。

这个模式的基本想法如下：首先我们拥有一个由许多对象构成的对象结构，这些对象的类都拥有一个accept方法用来接受访问者对象；访问者是一个接口，它拥有一个visit方法，这个方法对访问到的对象结构中不同类型的元素作出不同的反应；在对象结构的一次访问过程中，我们遍历整个对象结构，对每一个元素都实施accept方法，在每一个元素的accept方法中回调访问者的visit方法，从而使访问者得以处理对象结构的每一个元素。我们可以针对对象结构设计不同的实在的访问者类来完成不同的操作。

访问者模式使得我们可以在传统的单分派语言（如Smalltalk、Java和C++）中模拟双分派技术。对于支持多分派的语言（如CLOS），访问者模式已经内置于语言特性之中了，从而不再重要。

Python的例子
---------

```
"""
Visitor pattern example.
"""

from abc import ABCMeta, abstractmethod

NOT\_IMPLEMENTED = "You should implement this."

class CarElement:
    \_\_metaclass\_\_ = ABCMeta
    @abstractmethod
    def accept(self, visitor):
        raise NotImplementedError(NOT\_IMPLEMENTED)

class Body(CarElement):
    def accept(self, visitor):
        visitor.visitBody(self)

class Engine(CarElement):
    def accept(self, visitor):
        visitor.visitEngine(self)

class Wheel(CarElement):
    def \_\_init\_\_(self, name):
        self.name = name
    def accept(self, visitor):
        visitor.visitWheel(self)

class Car(CarElement):
    def \_\_init\_\_(self):
        self.elements = [
            Wheel("front left"), Wheel("front right"),
            Wheel("back left"), Wheel("back right"),
            Body(), Engine()
        ]

    def accept(self, visitor):
        for element in self.elements:
            element.accept(visitor)
        visitor.visitCar(self)

class CarElementVisitor:
    \_\_metaclass\_\_ = ABCMeta
    @abstractmethod
    def visitBody(self, element):
        raise NotImplementedError(NOT\_IMPLEMENTED)
    @abstractmethod
    def visitEngine(self, element):
        raise NotImplementedError(NOT\_IMPLEMENTED)
    @abstractmethod
    def visitWheel(self, element):
        raise NotImplementedError(NOT\_IMPLEMENTED)
    @abstractmethod
    def visitCar(self, element):
        raise NotImplementedError(NOT\_IMPLEMENTED)

class CarElementDoVisitor(CarElementVisitor):
    def visitBody(self, body):
        print("Moving my body.")
    def visitCar(self, car):
        print("Starting my car.")
    def visitWheel(self, wheel):
        print("Kicking my {} wheel.".format(wheel.name))
    def visitEngine(self, engine):
        print("Starting my engine.")

class CarElementPrintVisitor(CarElementVisitor):
    def visitBody(self, body):
        print("Visiting body.")
    def visitCar(self, car):
        print("Visiting car.")
    def visitWheel(self, wheel):
        print("Visiting {} wheel.".format(wheel.name))
    def visitEngine(self, engine):
        print("Visiting engine.")

car = Car()
car.accept(CarElementPrintVisitor())
car.accept(CarElementDoVisitor())

```

Java的例子
-------

```
 interface Visitor {
 void visit(Wheel wheel);
 void visit(Engine engine);
 void visit(Body body);
 void visit(Car car);
 }

 class Wheel {
 private String name;
 Wheel(String name) {
 this.name = name;
 }
 String getName() {
 return this.name;
 }
 void accept(Visitor visitor) {
 visitor.visit(this);
 }
 }
 
 class Engine {
 void accept(Visitor visitor) {
 visitor.visit(this);
 }
 }

 class Body {
 void accept(Visitor visitor) {
 visitor.visit(this);
 }
 }

 class Car {
 private Engine engine = new Engine();
 private Body body = new Body();
 private Wheel[] wheels 
 = { new Wheel("front left"), new Wheel("front right"),
 new Wheel("back left") , new Wheel("back right") };
 void accept(Visitor visitor) {
 visitor.visit(this);
 engine.accept(visitor);
 body.accept(visitor);
 for (int i = 0; i < wheels.length; ++ i)
 wheels[i].accept(visitor);
 }
 }

 class PrintVisitor implements Visitor {
 public void visit(Wheel wheel) {
 System.out.println("Visiting "+ wheel.getName()
 + "wheel");
 }
 public void visit(Engine engine) {
 System.out.println("Visiting engine");
 }
 public void visit(Body body) {
 System.out.println("Visiting body");
 }
 public void visit(Car car) {
 System.out.println("Visiting car");
 }
 }

 public class VisitorDemo {
 static public void main(String[] args) {
 Car car = new Car();
 Visitor visitor = new PrintVisitor();
 car.accept(visitor);
 }
 }

```

一个实际的例子
-------

这个例子是Htmlparser计划（页面存档备份，存于）里的一段示例。为获得一个Web页面的所有内容，采用如下的方式使用类 TextExtractingVisitor:

```
Parser parser = new Parser("");
TextExtractingVisitor visitor = new TextExtractingVisitor();
parser.visitAllNodesWith(visitor);
System.out.println(visitor.getExtractedText());
```

参考条目
----

* 软件设计模式
* 组合模式

  


|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 

| * 
* 论
* 编
软件设计模式 |
| --- |
|  |
| 设计模式 | 

|  |  |
| --- | --- |
| 创建型 | 
* 抽象工厂
* 生成器
* 工厂方法
* 惰性初始
* 原型
* 单例

 |
|  |
| 结构型 | 
* 适配器
* 桥接
* Composite（英语：）
* 修饰
* 外观
* 享元
* 代理

 |
|  |
| 行为型 | 
* 责任链
* 命令
* Interpreter（英语：）
* 迭代器
* 中介者
* Memento（英语：）
* 观察者
* Specification（英语：）
* State（英语：）
* 策略
* 模板方法
* 访问者

 |

 |
|  |
| 并行模式 | 
* 主动对象（英语：）
* 阻止（英语：）
* Binding properties（英语：）
* 双重检查锁定模式
* 异步方法调用
* Future与promise
* Guarded suspension（英语：）
* Join（英语：）
* 锁
* Messaging（英语：）
* 监视器
* Proactor（英语：）
* 反应器
* 读写锁
* 调度
* 线程池
* 线程局部存储

 |
|  |
| 架构模式 | 
* ADR（英语：）
* 主动记录
* Broker（英语：）
* 主從式架構
* cbd
* DAO
* DDD
* Data transfer object（英语：）
* Front controller（英语：）
* Identity map（英语：）
* Interceptor（英语：）
* 控制反转
* MVC
* 微服務
* MVP
* 單體式應用程式
* 多层架构
* *n*-tier（英语：）
* Naked objects（英语：）
* P2P
* 发布/订阅
* REST
* SOA
* Specification（英语：）

 |
|  |
| 云分布式 | 
* 断路器
* CQRS（英语：）
* 补偿交易（英语：）
* 索引表
* 领导者选举（英语：）
* MapReduce
* 物化视图（英语：）
* 管道
* 过滤器（英语：）
* 发布/订阅
* 分片（英语：）
* 节流（英语：）

 |
|  |
| 其他模式 | 
* Blackboard（英语：）
* Business delegate（英语：）
* Composite entity（英语：）
* 委托
* 依赖注入
* Intercepting filter（英语：）
* 惰性載入
* Method chaining（英语：）
* 模拟对象
* 空对象
* 对象池
* Servant（英语：）
* Twin（英语：）
* Type tunnel（英语：）

 |
|  |
| 书籍 | 
* 设计模式：可复用面向对象软件的基础
* 企业集成模式（英语：）

 |
|  |
| 人物 | 
* 克里斯托佛·亚历山大
* 埃里希·伽瑪
* Ralph Johnson（英语：）
* John Vlissides（英语：）
* 葛來迪·布區
* 肯特·貝克
* 沃德·坎宁安
* 马丁·福勒
* Robert Martin（英语：）
* Jim Coplien（英语：）
* Douglas Schmidt（英语：）
* Linda Rising

 |
|  |
| 社区 | 
* The Hillside Group（英语：）
* The Portland Pattern Repository（英语：）

 |

 |