设计模式之访问者模式

结构

访问者模式

说明

Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.

封装一些施加于某种数据结构元素之上的操作。一旦这些操作需要修改,接受这个操作的数据结构可以保持不变。

适用条件

访问者模式适用于数据结构相对稳定的系统,它把数据结构和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对自由的演化。

实现

interface ICarElementVisitor {

   void Visit(Wheel wheel);

   void Visit(Engine engine);

   void Visit(Body body);

   void Visit(Car car);

}

interface ICarElement {

   void Accept(ICarElementVisitor visitor);

}

class Wheel : ICarElement {

   public string Name {
      get;
      private set;
   }

   public Wheel(string name) {
      this.Name = name;
   }

   public void Accept(ICarElementVisitor visitor) {
      visitor.Visit(this);
   }

}

class Engine : ICarElement {

   public void Accept(ICarElementVisitor visitor) {
      visitor.Visit(this);
   }

}

class Body : ICarElement {

   public void Accept(ICarElementVisitor visitor) {
      visitor.Visit(this);
   }

}

class Car : ICarElement {

   private readonly ICarElement[] _elements;

   public Car() {
      this._elements = new ICarElement[] {
         new Wheel("front left"),
         new Wheel("front right"),
         new Wheel("back left"),
         new Wheel("back right"),
         new Body(),
         new Engine()
      };
   }

   public void Accept(ICarElementVisitor visitor) {
      foreach (var element in _elements) {
         element.Accept(visitor);
      }
      visitor.Visit(this);
   }
}

class CarElementPrintVisitor : ICarElementVisitor {
   
   public void Visit(Wheel wheel) {
      Console.WriteLine("visiting {0} wheel", wheel.Name);
   }

   public void Visit(Engine engine) {
      Console.WriteLine("visiting engine");
   }

   public void Visit(Body body) {
      Console.WriteLine("visiting body");
   }

   public void Visit(Car car) {
      Console.WriteLine("visitig car");
   }

}

class CarElementDoVisitor : ICarElementVisitor {

   public void Visit(Wheel wheel) {
      Console.WriteLine("kicking my {0} wheel", wheel.Name);
   }

   public void Visit(Engine engine) {
      Console.WriteLine("starting my engine");
   }

   public void Visit(Body body) {
      Console.WriteLine("moving my body");
   }

   public void Visit(Car car) {
      Console.WriteLine("starting my car");
   }
}

class Program {

   static void Main(string[] args) {

      var car = new Car();
      car.Accept(new CarElementPrintVisitor());
      car.Accept(new CarElementDoVisitor());

      Console.ReadKey();
   }

}