设计模式系列漫谈之十三 - 访问者模式

有这么一则笑话:

         话说有对一年轻夫妇生了一对双胞胎男孩。俩小子长得一模一样,还特别调皮。 平时一般都是妈妈照顾俩小子。可是有一天, 妈妈出差了,晚上爸爸给俩小子胎洗完澡,把他放到床上,催他们快睡觉,小宝就笑起来了:“哥哥都洗两次了,我都还没洗澡呢。”。爸爸:“还好不是喂饭” 。

访问者模式(Visitor)解决方案

      访问者模式适用于数据结构相对稳定的系统(两个小孩、负责喂饭和洗澡),它把数据结构和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对自由地演化。数据结构的每一个节点都可以接受一个访问者的调用,此节点向访问者对象传入节点对象,而访问者对象则反过来执行节点对象的操作。这样的过程叫做"双重分派"。节点调用访问者,将它自己传入,访问者则将某算法针对此节点执行。

访问者模式涉及到抽象访问者角色、具体访问者角色、抽象节点角色、具体节点角色、结构对象角色以及客户端角色。
抽象访问者(Visitor)角色:声明了一个或者多个访问操作,形成所有的具体元素角色必须实现的接口。如Visitor类
具体访问者(ConcreteVisitor)角色:实现抽象访问者角色所声明的接口,也就是抽象访问者所声明的各个访问操作。 如Wash类、Feed类。
抽象节点(Element)角色:声明一个接受操作,接受一个访问者对象作为一个参量。如Child类。
具体节点(ConcreteElement)角色:实现了抽象元素所规定的接受操作。如Son类。
结构对象(ObiectStructure)角色:可以遍历结构中的所有元素;如ObiectStructure


Visitor类如下:
public abstract class Visitor
{
    
public abstract void Visitor(Son son);
}
Wash类如下:
public class Wash:Visitor
{
    
public override void Visitor(Son son)
    {
        son.Washed
=true;
    }
}
Feed类如下:
public class Feed:Visitor
{
    
public override void Visitor(Son son)
    {
        son.Feeded
=true;
    }
}
Child类如下:
public abstract class Child
{
    
public string Name;
    
public bool Washed=false;
    
public bool Feeded=false;
    
public Child(string name)
    {
        Name
=name;
    }
    
public abstract void Accept(Visitor visitor);
}
Son类如下:
public class Son:Child
{
    
public Son(string name):base(name)
    {
    }
    
public override void Accept(Visitor visitor)
    {
        visitor.Visitor(
this);
    }
}
ObiectStructure类如下:
public class ObiectStructure
{
    
private List<Child> list=new List<Child>();
    
    
public void Add(Child ch)
    {
        list.Add(ch);
    }
    
public void Remove(Child ch)
    {
        list.Remove(ch);
    }
    
public void TakeCareofChildren(Visitor visitor)
    {
        
foreach(Child ch in list)
        {
            ch.Accept(visitor);
        }
    }
}
客户端调用如下:
public class Client
{
    
public static void Main()
    {
        ObjectStructure obj
=new ObjectStructure();
        obj.Add(
new Son("小宝"));
        obj.Add(
new Son("大宝"));

        Wash w
=new Wash();
        obj.TakeCareofChildren(w);

        Feed f
=new Feed();
        obj.TakeCareofChildren(f);
    }
}
posted @ 2008-01-09 20:53  李华星  阅读(703)  评论(2编辑  收藏  举报