Visitor 访问者模式
意图
表示一个作用于某对象结构的各个元素的操作,他可以在不改变各元素的前提下定义作用于这些元素的新的操作。
public abstract class Shape
{
public abstract void Draw();
}
public class Rectangle :Shape
{
public override void Draw()
{
//
}
}
public calss Circle:Shape
{
public override void Draw()
{
//
}
}
假设现在Shape 需要新增加一个特性MoveTo操作,它所有的子类都需要添加一个Moveto的Override方法。
public abstract calss Shape
{
public abstract void Draw()
publci abstract void MoveTo(Point p);
}
改进代码
public abstract class Shape
{
public abstract void Draw();
//预料到未来可能会做的操作
public abstract void Accpt(SharpVisitor v);
}
public abstract class ShapeVisitor
{
public abstract void Visit(Recctangle shape)
public abstract void Visit(Cirele shape);
public abstract void Visit(Line shape);
}
public class Rectangle:Shape
{
public override void Draw()
{
//
}
}
public voerride void Accpte(ShapeVisitor v)
{
v.Visit(this);//调用方法
}
public class Cirele:Shape
{
public override void Draw()
{
//
}
public override void Accept(ShpeVistor v)
{
v.Visit(this);
}
}
public class Line:Shape
{
public override void Draw()
{
//
}
public override void Accept(ShapeVisitor v)
{
v.Visit(this);
}
}
虽然子类的重载方法都是一样的代码,但是不能放在基类中写成Visit方法。因为首先Visit方法接受的类型不是多态类型,而是具体类型。传人的this是一种编译时绑定,他是一种静态多态。如果是在基类中写Accept虚方法,里面写上v.visit(this).编译的时候就会出错,因为Visit方法里接收的没有shape类型,所有只能在子类中重写。现在就给各个子类增加操作
public class MyVisitor:ShapeVistor
{
public override void Visit(Rectangle shape)
{
//
}
public abstract void Visit(Cirele shape)
{
}
public abstract void Visit(Line shape)
{
//
}
}
当然操作可能需要传入参数,我们可以为Accept方法添加一个上下文信息
public abstract class Shape
{
public abstract void Draw();
public abstract void Accept(ShapeVisitor v,Context context);
}
class App
{
ShapeVisitor vistor;
public App(ShapeVisitor visitor)
{
this.visitor = visitor;
}
public void Process(Shape shape)
{
shape.Accept(visitro);
}
}