访问者模式-Visitor
首先看一下男人与女人不同状态下反应的实现

代码结构图:

访问者模式-Visitor_ide

代码

状态的抽象类和人的抽象类
abstract class Action
{
//得到男人的结论或反应
public abstract void GetManConclusion(Man ConcreteElementA);
//得到女人的结论或反应
public abstract void GetWomanConclusion(Woman ConcreteElementB);
}
abstract class Person
{
//用来获得‘状态'对象
public abstract void Accept(Action visitor);
}
在这里关键在于人只分为男人与女人,分类稳定
具体状态类 成功
class Success : Action
{
public override void GetManConclusion(Man concreteElementA)
{
Console.WriteLine("{0} {1} 时,背后多半有一个伟大的女人",concreteElementA.GetType().Name,this.GetType().name);
}
public override void GetWomanConclusion(Man concreteElementB)
{
Console.WriteLine("{0} {1} 时,背后多半有一个不成功的男人",concreteElementA.GetType().Name,this.GetType().name);
}
}
//失败类
class Failing : Action
{
//类同
}class Man : Person
{
public override void Accept(Action visitor)
{
//首先在客户程序中将具体状态作为参数传递给男人类完成一次分派,然后男人类调用作为参数的具体状态中的方法’男人反应‘同时将自己(this)作为参数传递进去,这便完成了第二次分派
visitor.GetManConclusion(this);
}
}class Woman : Person
{
public override void Accept(Action visitor)
{
visitor.GetWomanConclusion(this);
}
}这里提到了双分派技术,双分派意味着得到执行的操作决定于请求的种类和两个接收者的类型。接收方法就是一个双分派的操作,它得到执行的操作不仅决定于’状态‘类的具体状态,还决定于它访问的’人‘的类别。
对象结构类
class ObjectStructure
{
private IList<Person> elements = new List<Person>();

public void Attach(Person element)
{
elements.Add(element);
}
public void Detack(Person element)
{
elements.Remove(element);
} public void Display(Action visitor)
{
foreach(Person e in elements)
{
e.Accept(visitor);
}
}
}---客户端代码---
static void Main(string[] args)
{
ObjectStructure o = new ObjectStructrue();
o.Attach(new Man());
o.Attach(new Woman()); //成功时的反应
Success v1 = new Success();
o.Display(v1); //失败时的反应
Failing v2 = new Failing();
o.Display(v2); Console.Read();
}

访问者模式(Visitor),表示一个作用于某个对象结构中的各元素的操作,它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
访问者模式结构图:

访问者模式-Visitor_访问者_02


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

访问者模式的目的是要把处理从数据结构分离出来。

访问者模式的优点就是增加新的操作容易,因为增加新的操作意味着增加一个新的访问者。访问者模式将有关的行为集中到一个访问者对象中。

缺点其实也就是使增加新的数据结构变得困难。

访问者模式可以说是最复杂的的一个模式。

代码实现

abstract class Visitor
{
public abstract void VisitConcreteElementA(ConcreteElementA concreteElementA);
public abstract void VisitConcreteElementB(ConcreteElementB concreteElementB);
}具体访问者类
class ConcreteVisitor1 : Visitor
{
public override void VisitConcreteElementA(ConcreteElementA concreteElementA)
{
Console.WriteLine("{0} 被 {1} 访问",concreteElementA.GetType().name,this.GetType().Name);
}
public override void VisitConcreteElementB(ConcreteElementB concreteElementB)
{
Console.WriteLine("{0} 被 {1} 访问",concreteElementB.GetType().name,this.GetType().Name);
}
}
class ConcreteVisitor2 : Visitor
{
public override void VisitConcreteElementA(ConcreteElementA concreteElementA)
{
Console.WriteLine("{0} 被 {1} 访问",concreteElementA.GetType().name,this.GetType().Name);
}
public override void VisitConcreteElementB(ConcreteElementB concreteElementB)
{
Console.WriteLine("{0} 被 {1} 访问",concreteElementB.GetType().name,this.GetType().Name);
}
}Element类,定义一个Accept操作,它以一个访问者为参数
abstract class Element
{
public abstract void Accept(Visitor visitor);
}
class ConcreteElementA : Element
{
public override void Accept(Visitor visitor)
{
visitor.VisitorConcreteElementA(this);
}
public void OperationA()
{}
}
class ConcreteElementB : Element
{
public override void Accept(Visitor visitor)
{
visitor.VisitorConcreteElementB(this);
}
public void OperationA()
{}
}
ObjectStructure类,能枚举它的元素,可以提供一个高层的接口以允许访问者访问它的元素
class ObjectStructure
{
private IList<Element> elements = new List<Element>();

public void Attach(Element element)
{
elements.Add(element);
}
public void Detack(Element element)
{
elements.Remove(element);
} public void Display(Action visitor)
{
foreach(Element e in elements)
{
e.Accept(visitor);
}
}
}---客户端代码---
static void Main(string[] args)
{
ObjectStructure o = new ObjectStructrue();
o.Attach(new ConcreteElementA());
o.Attach(new ConcreteElementB()); ConcreteVisitor1 v1 = new ConcreteVisitor1();
ConcreteVisitor2 v2 = new ConcreteVisitor2();
o.Accept(v1);
o.Accept(v2); Console.Read();
}