几天前给学生上课,一个学生问我用Delegate与Event实现Observer模式与不用它们实现到底有什么区别?我便讲了一个用奶箱订报纸的故事。 现在很多人都同时在订报纸和牛奶,送报纸的和送牛奶的也会在楼门口钉上一个箱子,一来方便,二来也为自己做做广告。现在楼门口前钉的大大小小都是箱子,几乎挤满了所有可用的地方。报箱是那种长长的,而奶箱子则有些四四方方,上面都开了可口,用来投递的。我家原来订了奶,楼门口众多的奶箱中有一个就是我家的,可后来不打算订了,就留了个空奶箱在那里。最近又有订报纸的打算,可打量了一番门口大大小小的箱子,实在是拥挤不堪,难以放下另外一个报箱了。于是我想让他们把报纸投到奶箱里算了,还省了不少麻烦。可偏偏碰上一家送报的对我说,我只会把报纸投到报箱中,投到奶箱中的事我不会!也难怪,他们公司没有使用Delegate!唉。

吕震宇

几天前给学生上课,一个学生问我用Delegate与Event实现Observer模式与不用它们实现到底有什么区别?我便讲了一个用奶箱订报纸的故事。

现在很多人都同时在订报纸和牛奶,送报纸的和送牛奶的也会在楼门口钉上一个箱子,一来方便,二来也为自己做做广告。现在楼门口前钉的大大小小都是箱子,几乎挤满了所有可用的地方。报箱是那种长长的,而奶箱子则有些四四方方,上面都开了可口,用来投递的。我家原来订了奶,楼门口众多的奶箱中有一个就是我家的,可后来不打算订了,就留了个空奶箱在那里。最近又有订报纸的打算,可打量了一番门口大大小小的箱子,实在是拥挤不堪,难以放下另外一个报箱了。于是我想让他们把报纸投到奶箱里算了,还省了不少麻烦。可偏偏碰上一家送报的对我说,我只会把报纸投到报箱中,投到奶箱中的事我不会!也难怪,他们公司没有使用Delegate!唉。

设计模式随笔-用奶箱订报纸 (转)_System

using System;
using System.Collections;

public interface IMilkBox
{
  void PutMilkIn(string s);
}

public interface INewsPaperBox
{
  void PutNewsPaperIn(string s);
}

public class Subscriber : INewsPaperBox, IMilkBox  
{
  public string name;

  public Subscriber(string name)
  
{
    this.name = name;
  }

  public void PutNewsPaperIn(string s)
  
{
    Console.WriteLine("{0}在报箱里收到送来的{1}",name, s);
  }

  public void PutMilkIn(string s)
  
{
    Console.WriteLine("{0}在奶箱里收到送来的{1}",name, s); 
  }
}

public class NewsPaperSender
{
  protected ArrayList subscribers = new ArrayList();

  public void SendNewsPaper()
  
{
    foreach(INewsPaperBox newsPaperBox in subscribers)
      newsPaperBox.PutNewsPaperIn("报纸");
  }

  public void Subscribe(INewsPaperBox newsPaperBox)
  
{ subscribers.Add(newsPaperBox); }
}

public class MilkSender
{
  protected ArrayList subscribers = new ArrayList();

  public void SendMilk()
  
{
    foreach(IMilkBox milkBox in subscribers)
      milkBox.PutMilkIn("牛奶");
  }

  public void Subscribe(IMilkBox milkBox)
  
{ subscribers.Add(milkBox); }
}

public class Client
{
  public static void Main( string[] args )
  
{
    MilkSender ms = new MilkSender();
    NewsPaperSender nps = new NewsPaperSender();
    
    Subscriber s1 = new Subscriber("张三");
    Subscriber s2 = new Subscriber("李四");
    Subscriber s3 = new Subscriber("王五");

    ms.Subscribe(s1);
    ms.Subscribe(s2);

    nps.Subscribe(s2);
    nps.Subscribe(s3);

    ms.SendMilk();
    Console.WriteLine("--------------------");
    nps.SendNewsPaper();
  }
}

后来我碰上了一家送报纸的比较灵活,只要是有口的箱子都可以送,不管是报箱还是奶箱,我的想法终于得到实现了,当然这也要归功于Delegate。

设计模式随笔-用奶箱订报纸 (转)_System

using System;

public delegate void SendableDelegate(string s);

public class Subscriber
{
  public string name;

  public Subscriber(string name)
  
{
    this.name = name;
  }

  public void PutNewsPaperIn(string s)
  
{
    Console.WriteLine("{0}在报箱里收到送来的{1}",name, s);
  }

  public void PutMilkIn(string s)
  
{
    Console.WriteLine("{0}在奶箱里收到送来的{1}",name, s); 
  }
}

public class NewsPaperSender
{
  public event SendableDelegate SendNewsPaperHandler;

  public void SendNewsPaper()
  
{
    if(SendNewsPaperHandler != null)
      SendNewsPaperHandler("报纸");
  }

  public void Subscribe(SendableDelegate sd)
  
{
    SendNewsPaperHandler += sd;
  }
}

public class MilkSender
{
  public event SendableDelegate SendMilkHandler;

  public void SendMilk()
  
{
    if(SendMilkHandler != null)
      SendMilkHandler("牛奶");
  }

  public void Subscribe(SendableDelegate sd)
  
{
    SendMilkHandler += sd;
  }
}

public class Client
{
  public static void Main( string[] args )
  
{
    MilkSender ms = new MilkSender();
    NewsPaperSender nps = new NewsPaperSender();
    
    Subscriber s1 = new Subscriber("张三");
    Subscriber s2 = new Subscriber("李四");
    Subscriber s3 = new Subscriber("哈哈!吕震宇");

    ms.Subscribe(new SendableDelegate(s1.PutMilkIn));
    ms.Subscribe(new SendableDelegate(s2.PutMilkIn));

    nps.Subscribe(new SendableDelegate(s2.PutNewsPaperIn));
    nps.Subscribe(new SendableDelegate(s3.PutMilkIn));

    ms.SendMilk();
    Console.WriteLine("--------------------");
    nps.SendNewsPaper();
  }
}

呵呵,不知道这回有没有搞清楚Delegate的作用?

设计模式随笔-用奶箱订报纸 (转)_System_03