热门问题
时间线
聊天
视角
访问者模式
来自维基百科,自由的百科全书
Remove ads
访问者模式是一种将算法与对象结构分离的软件设计模式。 访问者模式是一个由许多对象构成的对象结构,这些对象的类都拥有一个accept方法用来接受访问者对象;访问者是一个接口,它有一个visit方法,这个方法对访问到的对象结构中不同类型的元素作出相應的動作;在对象结构的访问过程中,visit方法遍历整个对象结构,对每一个元素都实施accept方法,在每一个元素的accept方法中回调访问者的visit方法,从而使访问者得以处理对象结构的每一个元素。我们可以针对对象结构设计不同的实在的访问者类来完成不同的操作。
![]() |

访问者模式使得在传统的单分派语言(如Smalltalk、Java和C++)中模拟双分派技术。对于支持多分派的语言(如CLOS),访问者模式已经在其语言特性之中了,而不再重要。
Remove ads
Python的例子
from abc import ABCMeta, abstractmethod
class CarElement(metaclass=ABCMeta):
@abstractmethod
def accept(self, visitor): pass
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): pass
@abstractmethod
def visitEngine(self, element): pass
@abstractmethod
def visitWheel(self, element): pass
@abstractmethod
def visitCar(self, element): pass
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())
Visiting front left wheel.
Visiting front right wheel.
Visiting back left wheel.
Visiting back right wheel.
Visiting body.
Visiting engine.
Visiting car.
>>> car.accept(CarElementDoVisitor())
Kicking my front left wheel.
Kicking my front right wheel.
Kicking my back left wheel.
Kicking my back right wheel.
Moving my body.
Starting my engine.
Starting my car.
Remove ads
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);
}
}
Remove ads
一个实际的例子
这个例子是Htmlparser计划(页面存档备份,存于互联网档案馆)里的一段示例。为获得一个Web页面的所有内容,采用以下的方式使用类 TextExtractingVisitor:
Parser parser = new Parser("http://pageIwantToParse.com[永久失效連結]"); TextExtractingVisitor visitor = new TextExtractingVisitor(); parser.visitAllNodesWith(visitor); System.out.println(visitor.getExtractedText());
参考条目
- 软件设计模式
- 组合模式
Wikiwand - on
Seamless Wikipedia browsing. On steroids.
Remove ads