访问者模式

✍ dations ◷ 2025-02-23 19:35:49 #访问者模式

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

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

参考条目

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


相关

  • 元嘉元嘉(424年—453年)是南朝宋皇帝宋文帝刘义隆的年号,共计29年余。由于宋文帝的儿子刘劭弑父自立改元太初,后刘劭兵败被杀,刘骏即位。通常的帝系表将其后继位改元孝建的宋孝武帝当
  • 泌乳激素1n9d, 3d48, 1rw5· STAT protein nuclear translocation · regulation of JAK-STAT cascade · female pregnancy · regulation of multicellular organism growth
  • 斯勒格斯勒格(slug)是英制单位中的一种质量单位。若1磅力(lbF)的力作用在某物体上,此物体获得1 英尺/秒2(1 ft/s2)的加速度,则此物体的质量是1斯勒格。1 sl
  • 东蒙东蒙可以指:
  • 新西兰工党新西兰工党(毛利语:Rōpū Reipa o Aotearoa;英语:New Zealand Labour Party)是现今新西兰两大主要政党之一,是政治立场中间偏左的政党。在2011年大选中,工党赢得121个议会议席中的
  • 伊戈尔伊戈尔·费奥多罗维奇·斯特拉文斯基(俄语:Игорь Фёдорович Стравинский,1882年6月17日-1971年4月6日),又译斯特拉温斯基,俄国-法国-美国作曲家、钢琴家
  • 扬·弗依基克扬·弗依基克(捷克语:Jan Fojtík;1928年3月1日-),捷克斯洛伐克共产党领导人,捷克斯洛伐克共产党党媒杂志主编、中央书记处书记,曾短暂的担任过党校校长。1989年天鹅绒革命后,辞去一
  • 触控笔触控笔(stylus或是stylus pen)是一种小笔形的工具,用来输入指令到电脑屏幕、移动设备、绘图板等具有触摸屏的设备,用户可以透过触控笔点击触屏来选取文件或绘画。还有一种笔型的
  • 戈尔·加斯帕里恩戈尔·加斯帕里恩(亚美尼亚语:Գոհար Գասպարյան;英语:Gohar Gasparyan;1924年12月14日-2007年5月16日)是亚美尼亚的歌剧演唱者,被世人称作“亚美尼亚的夜莺”。她出生
  • 罗斯泰利峰坐标:46°47′20″N 9°59′36″E / 46.78889°N 9.99333°E / 46.78889; 9.99333罗斯泰利峰(Rosställispitz),是瑞士的山峰,位于该国东南部,由格劳宾登州负责管辖,属于锡尔夫雷塔