设计模式随笔-用奶箱订报纸 (转)
吕震宇
几天前给学生上课,一个学生问我用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();
}
}
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();
}
}
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的作用?