访问者模式是一种将算法与对象结构分离的软件设计模式。
这个模式的基本想法如下:首先我们拥有一个由许多对象构成的对象结构,这些对象的类都拥有一个accept方法用来接受访问者对象;访问者是一个接口,它拥有一个visit方法,这个方法对访问到的对象结构中不同类型的元素作出不同的反应;在对象结构的一次访问过程中,我们遍历整个对象结构,对每一个元素都实施accept方法,在每一个元素的accept方法中回调访问者的visit方法,从而使访问者得以处理对象结构的每一个元素。我们可以针对对象结构设计不同的实在的访问者类来完成不同的操作。
访问者模式使得我们可以在传统的单分派语言(如Smalltalk、Java和C++)中模拟双分派技术。对于支持多分派的语言(如CLOS),访问者模式已经内置于语言特性之中了,从而不再重要。
"""Visitor pattern example."""from abc import ABCMeta, abstractmethodNOT_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 = 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())