訪問者模式

Visitor, UML class diagram.
訪問者模式是一種將算法與對象結構分離的軟件設計模式。
訪問者模式是一個由許多對象構成的對象結構，這些對象的類都擁有一個accept方法用來接受訪問者對象；訪問者是一個接口，它有一個visit方法，這個方法對訪問到的對象結構中不同類型的元素作出相應的動作；在對象結構的訪問過程中，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 

**一個實際的例子**
這個例子是 Htmlparser計劃date=20040715035442 裡的一段示例。為獲得一個Web頁面的所有內容，採用以下的方式使用類 TextExtractingVisitor:
Parser parser = new Parser("http://pageIwantToParse.comfix-attempted=yes ");
TextExtractingVisitor visitor = new TextExtractingVisitor();
parser.visitAllNodesWith(visitor);
System.out.println(visitor.getExtractedText());

**參考條目**
 軟件設計模式- 組合模式