访问者模式![]() 访问者模式(英語:visitor pattern),是一种将算法与对象结构分离的软件设计模式[2]。在传统的单分派语言比如Smalltalk、Java和C++之中,访问者模式被用来模拟双分派。在支持多分派的语言如CLOS之中,访问者模式就不再需要了。 概述访问者模式是一个由许多对象构成的对象结构,这些对象的类都拥有一个 结构![]()
例子JavaJava的例子: import java.util.List;
interface CarElement {
void accept(CarElementVisitor visitor);
}
interface CarElementVisitor {
void visit(Body body);
void visit(Car car);
void visit(Engine engine);
void visit(Wheel wheel);
}
class Wheel implements CarElement {
private final String name;
public Wheel(final String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public void accept(CarElementVisitor visitor) {
visitor.visit(this);
}
}
class Body implements CarElement {
@Override
public void accept(CarElementVisitor visitor) {
visitor.visit(this);
}
}
class Engine implements CarElement {
@Override
public void accept(CarElementVisitor visitor) {
visitor.visit(this);
}
}
class Car implements CarElement {
private final List<CarElement> elements;
public Car() {
this.elements = List.of(
new Wheel("front left"), new Wheel("front right"),
new Wheel("back left"), new Wheel("back right"),
new Body(), new Engine()
);
}
@Override
public void accept(CarElementVisitor visitor) {
for (CarElement element : elements) {
element.accept(visitor);
}
visitor.visit(this);
}
}
class CarElementDoVisitor implements CarElementVisitor {
@Override
public void visit(Body body) {
System.out.println("Moving my body");
}
@Override
public void visit(Car car) {
System.out.println("Starting my car");
}
@Override
public void visit(Wheel wheel) {
System.out.println("Kicking my " + wheel.getName() + " wheel");
}
@Override
public void visit(Engine engine) {
System.out.println("Starting my engine");
}
}
class CarElementPrintVisitor implements CarElementVisitor {
@Override
public void visit(Body body) {
System.out.println("Visiting body");
}
@Override
public void visit(Car car) {
System.out.println("Visiting car");
}
@Override
public void visit(Engine engine) {
System.out.println("Visiting engine");
}
@Override
public void visit(Wheel wheel) {
System.out.println("Visiting " + wheel.getName() + " wheel");
}
}
public class VisitorDemo {
public static void main(final String[] args) {
Car car = new Car();
car.accept(new CarElementPrintVisitor());
car.accept(new CarElementDoVisitor());
}
}
输出: Visiting front left wheel
Visiting front right wheel
Visiting back left wheel
Visiting back right wheel
Visiting body
Visiting engine
Visiting car
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
PythonPython的例子: class Element():
def accept(self, visitor):
key = '_'+type(self).__name__+'__visit'
if key in visitor.__dir__():
visitor.__getattribute__(key)(self)
class Body(Element): pass
class Engine(Element): pass
class Wheel(Element):
def __init__(self, name):
self.name = name
class Car(Element):
def __init__(self):
self.element_list = [
Wheel("front left"), Wheel("front right"),
Wheel("back left"), Wheel("back right"),
Body(), Engine()]
def accept(self, visitor):
for element in self.element_list:
element.accept(visitor)
super().accept(visitor)
class Visitor():
@classmethod
def admit(cls, visitor_dict):
for key, value in visitor_dict.items():
type.__setattr__(cls, '_'+key+'__visit', value)
class PrintVisitor(Visitor): pass
def _print_body(self, body):
print(f"Visiting body.")
def _print_car(self, car):
print(f"Visiting car.")
def _print_wheel(self, wheel):
print(f"Visiting {wheel.name} wheel.")
def _print_engine(self, engine):
print(f"Visiting engine.")
print_visitor_dict = {
'Body': _print_body, 'Car': _print_car,
'Wheel': _print_wheel, 'Engine': _print_engine}
PrintVisitor.admit(print_visitor_dict)
class DoVisitor(Visitor): pass
def _do_body(self, body):
print(f"Moving my body.")
def _do_car(self, car):
print(f"Starting my car.")
def _do_wheel(self, wheel):
print(f"Kicking my {wheel.name} wheel.")
def _do_engine(self, engine):
print(f"Starting my engine.")
do_visitor_dict = {
'Body': _do_body, 'Car': _do_car,
'Wheel': _do_wheel, 'Engine': _do_engine}
DoVisitor.admit(do_visitor_dict)
这里的访问者的反射式实现方式,主要解决访问者模式中难于动态增加具体元素类的问题[4]。下面是其用例: >>> car = Car()
>>> car.accept(PrintVisitor())
Visiting front left wheel.
Visiting front right wheel.
Visiting back left wheel.
Visiting back right wheel.
Visiting body.
Visiting engine.
Visiting car.
>>> car.accept(DoVisitor())
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.
C#下面的C#例子,声明了一个独立的 using System;
namespace Wikipedia;
public interface Visitor {
void Visit(Literal literal);
void Visit(Addition addition);
}
public class ExpressionPrintingVisitor : Visitor {
public void Visit(Literal literal) {
Console.WriteLine(literal.Value);
}
public void Visit(Addition addition) {
double leftValue = addition.Left.GetValue();
double rightValue = addition.Right.GetValue();
var sum = addition.GetValue();
Console.WriteLine($"{leftValue} + {rightValue} = {sum}");
}
}
public abstract class Expression {
public abstract void Accept(Visitor v);
public abstract double GetValue();
}
public class Literal : Expression {
public Literal(double value) {
this.Value = value;
}
public double Value { get; set; }
public override void Accept(Visitor v) {
v.Visit(this);
}
public override double GetValue() {
return Value;
}
}
public class Addition : Expression {
public Addition(Expression left, Expression right) {
Left = left;
Right = right;
}
public Expression Left { get; set; }
public Expression Right { get; set; }
public override void Accept(Visitor v) {
Left.Accept(v);
Right.Accept(v);
v.Visit(this);
}
public override double GetValue() {
return Left.GetValue() + Right.GetValue();
}
}
public static class Program {
public static void Main(string[] args) {
// Emulate 1 + 2 + 3
var e = new Addition(
new Addition(
new Literal(1),
new Literal(2)
),
new Literal(3)
);
var printingVisitor = new ExpressionPrintingVisitor();
e.Accept(printingVisitor);
Console.ReadKey();
}
}
参考条目引用
|
Index:
pl ar de en es fr it arz nl ja pt ceb sv uk vi war zh ru af ast az bg zh-min-nan bn be ca cs cy da et el eo eu fa gl ko hi hr id he ka la lv lt hu mk ms min no nn ce uz kk ro simple sk sl sr sh fi ta tt th tg azb tr ur zh-yue hy my ace als am an hyw ban bjn map-bms ba be-tarask bcl bpy bar bs br cv nv eml hif fo fy ga gd gu hak ha hsb io ig ilo ia ie os is jv kn ht ku ckb ky mrj lb lij li lmo mai mg ml zh-classical mr xmf mzn cdo mn nap new ne frr oc mhr or as pa pnb ps pms nds crh qu sa sah sco sq scn si sd szl su sw tl shn te bug vec vo wa wuu yi yo diq bat-smg zu lad kbd ang smn ab roa-rup frp arc gn av ay bh bi bo bxr cbk-zam co za dag ary se pdc dv dsb myv ext fur gv gag inh ki glk gan guw xal haw rw kbp pam csb kw km kv koi kg gom ks gcr lo lbe ltg lez nia ln jbo lg mt mi tw mwl mdf mnw nqo fj nah na nds-nl nrm nov om pi pag pap pfl pcd krc kaa ksh rm rue sm sat sc trv stq nso sn cu so srn kab roa-tara tet tpi to chr tum tk tyv udm ug vep fiu-vro vls wo xh zea ty ak bm ch ny ee ff got iu ik kl mad cr pih ami pwn pnt dz rmy rn sg st tn ss ti din chy ts kcg ve