现在的位置: 首页 > 综合 > 正文

设计模式随笔-用奶箱订报纸

2013年02月21日 ⁄ 综合 ⁄ 共 3389字 ⁄ 字号 评论关闭

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

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

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。

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的作用?

抱歉!评论已关闭.