访问者模式

✍ dations ◷ 2025-12-08 17:13:55 #访问者模式

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

这个模式的基本想法如下:首先我们拥有一个由许多对象构成的对象结构,这些对象的类都拥有一个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())

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.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());

参考条目

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


相关

  • 品行障碍品行障碍(英语:Conduct disorder)也称为行为规范障碍,是指在青少年阶段的患者出现反复、持续的攻击性、反社会性、对立违抗性的行为障碍。这些行为违反了与年龄相适应的社会行为
  • 尼科尔夏尔·朱尔·亨利·尼科勒(Charles Jules Henri Nicolle,1866年9月21日-1936年2月28日)是一位法国细菌学家,曾经因为关于辨认出虱子为斑疹伤寒的传染者,而获得1928年诺贝尔生理学
  • 伊戈尔·布博尼季奇伊戈尔·布博尼季奇(克罗地亚语:Igor Bubnjić,1992年7月17日-),是一名克罗地亚足球运动员,现效力于意大利足球甲级联赛球队乌迪内斯。布博尼季奇在2007年进入克罗地亚球队斯拉文贝
  • 国立台湾大学医学院校区国立台湾大学医学院校区简称医学院校区,主要是国立台湾大学医学院所在的地方。校址位于台湾台北市中正区仁爱路一段1号。校区位于台北市市中心,北接内政部、立法院、监察院、
  • 中勘助中勘助(なか かんすけ,1885年5月22日-1965年5月3日),日本东京府东京市神田区(现东京都千代田区神田)出身作家、诗人。1913年至1914年,中勘助撰写的自传小说《银汤匙》于东京朝日新闻
  • 艾吉巴斯顿水厂艾吉巴斯顿水厂(英语:Edgbaston Waterworks)是英格兰伯明翰的一座水厂,建于1870年,其建筑由建筑师约翰·亨利·张伯伦(英语:John Henry Chamberlain)和威廉·马丁(英语:William Martin
  • 广岛县旗广岛县旗(日语:広島県旗/ひろしまけんき )是日本的47面都道府县旗之一。该条目是对广岛县旗以及广岛县章(日语:広島県章/ひろしまけんしょう )的解说。县章、县旗是在1966年(昭和41
  • 相葉裕樹相叶裕树(1987年10月1日-),原名相叶弘树,日本男演员。现隶属于Grand-Arts事务所。出身于日本千叶县船桥市。千叶县立船桥北高等学校毕业。
  • 弗拉纳峰坐标:70°22′S 63°59′E / 70.367°S 63.983°E / -70.367; 63.983弗拉纳峰(英语:Vrana Peak)是南极洲的山峰,位于麦克罗伯特森地,处于特恩布尔山西南面,属于查尔斯王子山脉的一
  • 垃圾时间垃圾时间(英语:Garbage time),是一个用在多种限时制体育赛事中的术语。指一场比赛中,双方队伍的分数差距太大,难以改变胜负结果时,其剩余的比赛时间就称之为垃圾时间。此时其中一方或双方的教练可能会指派后补人员替代主力上场,这样做的目的一方面是让候补人员增加经验,另一方面也可降低主力人员受伤的风险。棒球等运动赛事会规定分数差距到一定比数时,提前结束比赛。