訪問者模式

訪問者模式是一種將演算法與物件結構分離的軟體設計模式。這個模式的基本想法如下：首先我們擁有一個由許多物件構成的物件結構，這些物件的類都擁有一個accept方法用來接受訪問者物件；訪問者是一個介面，它擁有一個visit方法，這個方法對訪問到的物件結構中不同型別的元素作出不同的反應；在物件結構的一次訪問過程中，我們遍歷整個物件結構，對每一個元素都實施accept方法，在每一個元素的accept方法中回撥訪問者的visit方法，從而使訪問者得以處理物件結構的每一個元素。我們可以針對物件結構設計不同的實在的訪問者類來完成不同的操作。訪問者模式使得我們可以在傳統的單分派語言，訪問者模式已經內置於語言特性之中了，從而不再重要。Python的例子.Visitor pattern example.from abc import ABCMeta, abstractmethodNOT_IMPLEMENTED = "You should implement this."class CarElement:__metaclass__ = ABCMeta@abstractmethoddef 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 = namedef 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@abstractmethoddef visitBody(self, element):raise NotImplementedError(NOT_IMPLEMENTED)@abstractmethoddef visitEngine(self, element):raise NotImplementedError(NOT_IMPLEMENTED)@abstractmethoddef visitWheel(self, element):raise NotImplementedError(NOT_IMPLEMENTED)@abstractmethoddef 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 &lt; 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("http://pageIwantToParse.com");TextExtractingVisitor visitor = new TextExtractingVisitor();parser.visitAllNodesWith(visitor);System.out.println(visitor.getExtractedText());