跳转到内容

访问者模式:修订间差异

维基百科,自由的百科全书
删除的内容 添加的内容
Zy26留言 | 贡献
typo
InternetArchiveBot留言 | 贡献
补救1个来源,并将0个来源标记为失效。) #IABot (v2.0.8
 
(未显示29个用户的38个中间版本)
第1行: 第1行:
{{multiple issues|
{{copyedit|time=2013-10-02T03:03:59+00:00}}
{{expand|time=2013-10-02T03:03:59+00:00}}
{{refimprove|time=2013-10-02T03:03:59+00:00}}
}}
[[File:Visitor UML class diagram.svg|thumb|400px|Visitor, [[UML]] class diagram.]]

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


这个模式的基本想法如下:首先我们拥有一个由许多[[对象 (计算机)|对象]]构成的对象结构,这些对象的[[类 (计算机)|类]]都拥有一个accept[[方法 (计算机)|方法]]用来接受访问者对象;访问者是一个接口,它拥有一个visit方法,这个方法对访问到的对象结构中不同类型的元素作出不同的反应;在对象结构的一次访问过程中,我们遍历整个对象结构,对每一个元素都实施accept方法,在每一个元素的accept方法中[[回调]]访问者的visit方法,从而使访问者得以处理对象结构的每一个元素。我们可以针对对象结构设计不同的实在的访问者类来完成不同的操作。
这个模式的基本想法如下:首先我们拥有一个由许多[[对象 (计算机)|对象]]构成的对象结构,这些对象的[[类 (计算机)|类]]都拥有一个accept[[方法 (计算机)|方法]]用来接受访问者对象;访问者是一个接口,它拥有一个visit方法,这个方法对访问到的对象结构中不同类型的元素作出不同的反应;在对象结构的一次访问过程中,我们遍历整个对象结构,对每一个元素都实施accept方法,在每一个元素的accept方法中[[回调]]访问者的visit方法,从而使访问者得以处理对象结构的每一个元素。我们可以针对对象结构设计不同的实在的访问者类来完成不同的操作。


访问者模式使得我们可以在传统的[[单分派]]语言(如[[Smalltalk]]、[[Java]]和[[C++|C++]])中模拟[[双分派]]技术。对于支持[[多分派]]的语言(如[[CLOS]]),访问者模式已经内置于语言特性之中了,从而不再重要。
访问者模式使得我们可以在传统的[[单分派]]语言(如[[Smalltalk]]、[[Java]]和[[C++]])中模拟[[双分派]]技术。对于支持[[多分派]]的语言(如[[CLOS]]),访问者模式已经内置于语言特性之中了,从而不再重要。

== [[Python]]的例子 ==
<syntaxhighlight lang="python">
"""
Visitor pattern example.
"""

from abc import ABCMeta, abstractmethod

NOT_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 = [
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):
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):
== [[Python]]的例子==
def visitBody(self, body):
class Wheel:
def __init__(self,name):
print("Visiting body.")
self.name = name
def visitCar(self, car):
def accept(self,visitor):
print("Visiting car.")
visitor.visitWheel(self)
def visitWheel(self, wheel):
print("Visiting {} wheel.".format(wheel.name))
def visitEngine(self, engine):
class Engine:
def accept(self,visitor):
print("Visiting engine.")
visitor.visitEngine(self)
class Body:
def accept(self,visitor):
visitor.visitBody(self)
class Car:
def __init__(self):
self.engine = Engine()
self.body = Body()
self.wheels = [ Wheel("front left"), Wheel("front right"),
Wheel("back left") , Wheel("back right") ]
def accept(self,visitor):
visitor.visitCar(self)
self.engine.accept( visitor )
self.body.accept( visitor )
for wheel in self.wheels:
wheel.accept( visitor )
class PrintVisitor:
def visitWheel(self,wheel):
print "Visiting "+wheel.name+" wheel"
def visitEngine(self,engine):
print "Visiting engine"
def visitBody(self,body):
print "Visiting body"
def visitCar(self,car):
print "Visiting car"
car = Car()
visitor = PrintVisitor()
car.accept(visitor)


car = Car()
==[[Java]]的例子==
car.accept(CarElementPrintVisitor())
car.accept(CarElementDoVisitor())
</syntaxhighlight>


== [[Java]]的例子 ==
interface Visitor{
<syntaxhighlight lang="java">
interface Visitor {
void visit(Wheel wheel);
void visit(Wheel wheel);
void visit(Engine engine);
void visit(Engine engine);
第56行: 第107行:
}
}


class Wheel{
class Wheel {
private String name;
private String name;
Wheel(String name){
Wheel(String name) {
this.name = name;
this.name = name;
}
}
String getName(){
String getName() {
return this.name;
return this.name;
}
}
void accept(Visitor visitor){
void accept(Visitor visitor) {
visitor.visit(this);
visitor.visit(this);
}
}
}
}
class Engine{
class Engine {
void accept(Visitor visitor){
void accept(Visitor visitor) {
visitor.visit(this);
visitor.visit(this);
}
}
}
}


class Body{
class Body {
void accept(Visitor visitor){
void accept(Visitor visitor) {
visitor.visit(this);
visitor.visit(this);
}
}
}
}


class Car {

class Car{
private Engine engine = new Engine();
private Engine engine = new Engine();
private Body body = new Body();
private Body body = new Body();
第88行: 第138行:
= { new Wheel("front left"), new Wheel("front right"),
= { new Wheel("front left"), new Wheel("front right"),
new Wheel("back left") , new Wheel("back right") };
new Wheel("back left") , new Wheel("back right") };
void accept(Visitor visitor){
void accept(Visitor visitor) {
visitor.visit(this);
visitor.visit(this);
engine.accept( visitor );
engine.accept(visitor);
body.accept( visitor );
body.accept(visitor);
for(int i=0; i<wheels.length; ++i)
for (int i = 0; i < wheels.length; ++ i)
wheels[i].accept( visitor );
wheels[i].accept(visitor);
}
}
}
}


class PrintVisitor implements Visitor{
class PrintVisitor implements Visitor {
public void visit(Wheel wheel){
public void visit(Wheel wheel) {
System.out.println("Visiting "+wheel.getName()
System.out.println("Visiting " + wheel.getName()
+" wheel");
+ " wheel");
}
}
public void visit(Engine engine){
public void visit(Engine engine) {
System.out.println("Visiting engine");
System.out.println("Visiting engine");
}
}
public void visit(Body body){
public void visit(Body body) {
System.out.println("Visiting body");
System.out.println("Visiting body");
}
}
public void visit(Car car){
public void visit(Car car) {
System.out.println("Visiting car");
System.out.println("Visiting car");
}
}
}
}


public class VisitorDemo{
public class VisitorDemo {
static public void main(String[] args){
static public void main(String[] args) {
Car car = new Car();
Car car = new Car();
Visitor visitor = new PrintVisitor();
Visitor visitor = new PrintVisitor();
第120行: 第170行:
}
}
}
}
</syntaxhighlight>
== 一个实际的例子 ==


这个例子是[http://htmlparser.sourceforge.net/ Htmlparser计划]{{Wayback|url=http://htmlparser.sourceforge.net/ |date=20040715035442 }}里的一段示例。为获得一个Web页面的所有内容,采用如下的方式使用类 TextExtractingVisitor:
==一个实际的例子==


Parser parser = new Parser("http://pageIwantToParse.com{{dead link|date=2018年4月 |bot=InternetArchiveBot |fix-attempted=yes }}");
这个例子是[http://htmlparser.sourceforge.net/ Htmlparser计划]里的一段示例。为获得一个Web页面的所有内容,采用如下的方式使用类 TextExtractingVisitor:
TextExtractingVisitor visitor = new TextExtractingVisitor();
parser.visitAllNodesWith(visitor);
System.out.println(visitor.getExtractedText());


== 参考条目 ==
Parser parser = new Parser ("http://pageIwantToParse.com");
* [[软件设计模式]]
TextExtractingVisitor visitor = new TextExtractingVisitor ();
* [[组合模式]]
parser.visitAllNodesWith (visitor);
System.out.println (visitor.getExtractedText());


==参考条目==
*[[软件设计模式]]
*[[组合模式]]


{{软件设计模式}}
[[Category:软件设计模式]]
[[Category:软件设计模式]]

[[de:Besucher (Entwurfsmuster)]]
[[en:Visitor pattern]]

2021年5月17日 (一) 20:09的最新版本

Visitor, UML class diagram.

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

这个模式的基本想法如下:首先我们拥有一个由许多对象构成的对象结构,这些对象的都拥有一个accept方法用来接受访问者对象;访问者是一个接口,它拥有一个visit方法,这个方法对访问到的对象结构中不同类型的元素作出不同的反应;在对象结构的一次访问过程中,我们遍历整个对象结构,对每一个元素都实施accept方法,在每一个元素的accept方法中回调访问者的visit方法,从而使访问者得以处理对象结构的每一个元素。我们可以针对对象结构设计不同的实在的访问者类来完成不同的操作。

访问者模式使得我们可以在传统的单分派语言(如SmalltalkJavaC++)中模拟双分派技术。对于支持多分派的语言(如CLOS),访问者模式已经内置于语言特性之中了,从而不再重要。

Python的例子

[编辑]
"""
Visitor pattern example.
"""

from abc import ABCMeta, abstractmethod

NOT_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 = [
            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):
        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[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());

参考条目

[编辑]