动机:
在软件构建过程中,由于需求的改变,某些类层次结构中常常需要增加新的行为(方法),如果直接在基类中做这样的改变,将会给子类带来很繁重的变更负担,甚至破坏原有设计。
如何在不更改类层次结构的前提下,在运行时根据需要透明的为类层次结构上的各个类动态添加新的操作,从而避免上述问题?
意图:
标识一个作用于某对象结构中的各元素的操作。它可以在不改变各元素的类的前提下定义作用于这些元素的新的操作。
public abstract class Shape
{
public abstract void Draw();
public abstract void MoveTo(Point p);
}
public class Rectangle : Shape
{
public override void Draw()
{
}
}
public class Circle : Shape
{
public override void Draw()
{
}
}
public class Line : Shape
{
public override void Draw()
{
}
}
在上述代码中,我们有一个抽象基类Shape,他定义了抽象方法Draw,Rectangle、Circle、Line继承了Shape类的方法,并且实现了Draw方法,但是当我们需要增加一个方法MoveTo时,我们必不可少的需要在各个子类中重写MoveTo方法,那么现在就带来了一个问题,当我们基类的方法不能完全确定,也就是稳定的时候,我们如何来进行解藕。
public abstract class Shape
{
public abstract void Draw();
//预料到将来会引入新的操作
public abstract void Accept(ShapeVisitor visitor);
}
public abstract class ShapeVisitor
{
//重载的关系,Visit方法参数不是基类型,是具体类型
public abstract void Visit(Rectangle shape);
public abstract void Visit(Circle shape);
public abstract void Visit(Line shape);
}
public class MyVisitor : ShapeVisitor
{
public override void Visit(Rectangle shape)
{
//增加对Rectangle的操作
}
public override void Visit(Circle shape)
{
//增加对Circle的操作
}
public override void Visit(Line shape)
{
//增加对Line的操作
}
}
public class Rectangle : Shape
{
public override void Draw()
{
}
public override void Accept(ShapeVisitor visitor)
{
//这里是编译时确定的,不是运行时确定
//如果这个调用写到Shape基类里,编译器编译的时候
//不知道编译那个方法。编译会报错,因为没有
//Visit(Shape shape)方法。
visitor.Visit(this);
}
}
public class Circle : Shape
{
public override void Draw()
{
}
public override void Accept(ShapeVisitor visitor)
{
visitor.Visit(this);
}
}
public class Line : Shape
{
public override void Draw()
{
}
public override void Accept(ShapeVisitor visitor)
{
visitor.Visit(this);
}
}
class App
{
ShapeVisitor visitor;
public App(ShapeVisitor visitor)
{
this.visitor = visitor;
}
public void Process(Shape shape)
{
//两处多态:
//1、Accept方法的调用对象Shape
//2、Accept方法的参数Visitor
shape.Accept(visitor);
}
}
class Program
{
static void Main(string[] args)
{
App app = new App(new MyVisitor());
app.Process(new Line());
}
}
现在,我们在Shape类中定义了一个Accept方法,这个方法也是一个抽象方法,并且Rectangle、Circle、Line实现了Accept方法。并且Accept方法有一个参数ShapeVisitor。现在转到ShapeVisitor类,定义了Visit方法,
在软件构建过程中,由于需求的改变,某些类层次结构中常常需要增加新的行为(方法),如果直接在基类中做这样的改变,将会给子类带来很繁重的变更负担,甚至破坏原有设计。
如何在不更改类层次结构的前提下,在运行时根据需要透明的为类层次结构上的各个类动态添加新的操作,从而避免上述问题?
意图:
标识一个作用于某对象结构中的各元素的操作。它可以在不改变各元素的类的前提下定义作用于这些元素的新的操作。
public abstract class Shape
{
public abstract void Draw();
public abstract void MoveTo(Point p);
}
public class Rectangle : Shape
{
public override void Draw()
{
}
}
public class Circle : Shape
{
public override void Draw()
{
}
}
public class Line : Shape
{
public override void Draw()
{
}
}
在上述代码中,我们有一个抽象基类Shape,他定义了抽象方法Draw,Rectangle、Circle、Line继承了Shape类的方法,并且实现了Draw方法,但是当我们需要增加一个方法MoveTo时,我们必不可少的需要在各个子类中重写MoveTo方法,那么现在就带来了一个问题,当我们基类的方法不能完全确定,也就是稳定的时候,我们如何来进行解藕。
public abstract class Shape
{
public abstract void Draw();
//预料到将来会引入新的操作
public abstract void Accept(ShapeVisitor visitor);
}
public abstract class ShapeVisitor
{
//重载的关系,Visit方法参数不是基类型,是具体类型
public abstract void Visit(Rectangle shape);
public abstract void Visit(Circle shape);
public abstract void Visit(Line shape);
}
public class MyVisitor : ShapeVisitor
{
public override void Visit(Rectangle shape)
{
//增加对Rectangle的操作
}
public override void Visit(Circle shape)
{
//增加对Circle的操作
}
public override void Visit(Line shape)
{
//增加对Line的操作
}
}
public class Rectangle : Shape
{
public override void Draw()
{
}
public override void Accept(ShapeVisitor visitor)
{
//这里是编译时确定的,不是运行时确定
//如果这个调用写到Shape基类里,编译器编译的时候
//不知道编译那个方法。编译会报错,因为没有
//Visit(Shape shape)方法。
visitor.Visit(this);
}
}
public class Circle : Shape
{
public override void Draw()
{
}
public override void Accept(ShapeVisitor visitor)
{
visitor.Visit(this);
}
}
public class Line : Shape
{
public override void Draw()
{
}
public override void Accept(ShapeVisitor visitor)
{
visitor.Visit(this);
}
}
class App
{
ShapeVisitor visitor;
public App(ShapeVisitor visitor)
{
this.visitor = visitor;
}
public void Process(Shape shape)
{
//两处多态:
//1、Accept方法的调用对象Shape
//2、Accept方法的参数Visitor
shape.Accept(visitor);
}
}
class Program
{
static void Main(string[] args)
{
App app = new App(new MyVisitor());
app.Process(new Line());
}
}
现在,我们在Shape类中定义了一个Accept方法,这个方法也是一个抽象方法,并且Rectangle、Circle、Line实现了Accept方法。并且Accept方法有一个参数ShapeVisitor。现在转到ShapeVisitor类,定义了Visit方法,