Visitor访问者模式(行为型模式)
动机:
在软件构建过程中,由于需求的变化,一些类层次结构往往需要添加新的行为(方法)。如果直接在基类中进行这样的修改,会给子类带来沉重的修改负担,甚至会破坏原有的设计。
在不改变类层次结构的前提下,如何在运行时透明地为类层次结构上的每个类动态添加新操作,从而避免上述问题?
意图:
标识作用于对象结构中每个元素的操作。它可以定义作用于元素的新操作,而不改变它们的类。
公共抽象类Shape
{
公共抽象void Draw();
公共抽象void move to(p点);
}
公共类矩形:Shape
{
公共重写void Draw()
{
}
}
公共类圆:Shape
{
公共重写void Draw()
{
}
}
公共类行:Shape
{
公共重写void Draw()
{]矩形、圆形和线条继承Shape类的方法并实现draw方法。但是当我们需要添加一个方法MoveTo时,就需要在各个子类中重写MoveTo方法,所以现在就带来了一个问题。当我们的基类的方法没有完全确定,也就是稳定的时候,怎么解耦呢?
公共抽象类Shape
{
公共抽象void Draw();
//预计未来会引入新的操作
public abstract void accept(shape visitor visitor);
}
公共抽象类shape Visitor
{
/重载关系,visit方法的参数不是基类型,而是具体类型
公共抽象void visit(矩形形状);
公共抽象void访问(圆形);
公共抽象void访问(线形);[/Br/]}[/Br/]Public class my Visitor:Shape Visitor[/Br/]{[/Br/]Public Override Void visit(矩形形状)[/Br/]{[/Br/]}[/Br/][/Br/]{[/Br/]/Increase of Circle[/Br/]}[/Br/]Public Override Void visit(线条形状)
{
//增加line的操作 这是在编译时确定的,而不是在运行时确定的
//如果这个调用写入shape基类,编译器在编译时不知道要编译哪个方法
//。 编译将报告错误,因为没有
//Visit(Shape shape)方法。
访客。访(本);
}
}
公共类Circle : Shape
{
公共重写void Draw()
{
}
公共重写void Accept(Shape visitor visitor)
{
visitor。访(本);
}
}
公共类行:Shape
{
公共重写void Draw()
{
}
公共重写void Accept(Shape visitor visitor)
{
visitor。访(本);
}
}
类App
{
ShapeVisitor访问者;
公共App(ShapeVisitor访问者)
{
this . visitor = visitor;
}
public void process(shape shape)
{
/exam da提示:有两种多态性:
/1、Accept方法的调用对象shape
/2、Accept方法的参数visitor[
}
}
类程序
{
static void Main(string[]args)
{
App = new App(new
app。process(new Line());
}
}
现在,我们在Shape类中定义了一个Accept方法,也是一个抽象方法,矩形、圆形、直线实现了Accept方法。Accept方法有一个参数ShapeVisitor。现在转到ShapeVisitor类,定义访问方法,有三个重载。每个访问方法的参数都是Shape的派生类。在Rectangle、Circle和Line类中,我们实现的Accept方法是将这个指针传递给Visit方法。
现在有一个具体的MyVisitor类继承自ShapeVisitor类,在这个类中,每个Visit方法的重载根据传输的图形做具体的动作。
在App类的处理方法中,根据传入的graphic对象和visitor对象形成了两种多态性。当我们需要为Shape添加一个方法时,我们不需要重写Shape类及其派生类。我们只需要添加一个Visitor类,并将新添加的Visitor类传递给App。
重要:
Visitor模式实现了在运行时透明地向类层次结构上的每个类动态添加新操作,而不改变元素类的层次结构。
所谓双分布,即访问者模式,包括两种多态分布:第一种是Accept方法的多态判别;第二个是Visit方法的多态判别(重载)
Visitor模式的缺点是扩展类层次结构(增加新元素子类)会导致Visitor类的改变。因此,访问者模式使用户的元素类层的子结构稳定,但其中的操作经常面临频繁的变化。
当我们需要添加Shape的子类时,需要给ShapeVisitor类添加一个Visit函数,ShapeVisitor的每个派生类也必须添加。
0条评论