从老李打渔浅析C#中的委托/事件机制(1)

这几天在整理C#语言,发现还有很多东西由于没有真正用到,理解得都很肤浅。比如:委托,感觉就是一个函数指针,用来实现事件模型。直到今天看到一篇老外的文章,感觉理解加深了不少。于是决定结合自己的理解重新写一下,也算是总结吧。

紧耦合

从前,在东海边有个村子,有个渔夫叫老李,世代以打渔为生。而村里的王员外是老李的老客户,每天都要向老李买鲜鱼。因为这个村子只有老李一个渔夫,所以老李的生意非常红火,以至于王员外要想买到新鲜的鱼就一定要盯紧老李,否则就只能买到小鱼了。“老李,你随时给我电话,汇报打渔情况,我要买到最好的鱼,最新鲜的鱼,钱不是问题!”。于是就有了下面一幕:

FishMan.cs

using System;

namespace delegateMain
{
 ///
 /// FishMan 的摘要说明。
 ///
 public class FishMan
 {
  private Wang _wang;
  public FishMan()
  {
   //
   // TODO: 在此处添加构造函数逻辑
   //
  }
  public void Advise(Wang wang) { _wang = wang; }
  public void DoWork()
  {
   Console.WriteLine("渔夫老李: 王员外,我开始下网");
   if( _wang != null ) _wang.WorkStarted();

   Console.WriteLine("渔夫老李: 王员外,我正在打鱼中");
   if( _wang != null ) _wang.WorkProgressing();

   Console.WriteLine("渔夫老李: 王员外,我鱼打上来了");
   if( _wang != null )
   {
    int grade = _wang.WorkCompleted();
    Console.WriteLine("渔夫老李:卖得银两=" + grade);
   }
  }

}
}

Wang.cs

using System;

namespace delegateMain
{
 ///
 /// Wang 的摘要说明。
 ///
 public class Wang
 {
  public Wang()
  {
   //
   // TODO: 在此处添加构造函数逻辑
   //
  }
  public void WorkStarted() {Console.WriteLine("王员外:好的。"); }
  public void WorkProgressing() { Console.WriteLine("王员外:好的,好的。"); }
  public int WorkCompleted()
  {
   Console.WriteLine("王员外:老李你的鱼打上来多少,多少一斤?");
   return 2;

  }

 }
}

delegateMain.cs

using System;

namespace delegateMain
{
 ///
 /// Class1 的摘要说明。
 ///
 class FishManDemo
 {
  ///
  /// 应用程序的主入口点。
  ///
  [STAThread]
  static void Main(string[] args)
  {
   FishMan li = new FishMan();
   Wang WangYuanWai = new Wang();
   li.Advise(WangYuanWai);
   li.DoWork();

   Console.WriteLine("Main: 打鱼完成");
   Console.ReadLine();

  }
 }
}

http://xiekeli.blogbus.com/files/1168045873.gif

接口

后来张财主也要抢着买老李的鱼,而且也要老李及时向他反馈打渔的情况,于是老李觉得有必要搞个售前服务部对这些个财主员外们反馈信息。

IWorkerEvents.cs

using System;

namespace delegateMain
{
 ///
 /// IWorkerEvents 的摘要说明。
 ///
 public interface IWorkerEvents
 {
  void WorkStarted();
  void WorkProgressing();
  int WorkCompleted();

 }
}

Wang.cs

using System;

namespace delegateMain
{
 ///
 /// Wang 的摘要说明。
 ///
 public class Wang : IWorkerEvents
 {
  public void WorkStarted() {Console.WriteLine("王员外:好的。"); }
  public void WorkProgressing() { Console.WriteLine("王员外:好的,好的。"); }
  public int WorkCompleted()
  {
   Console.WriteLine("王员外:老李你的鱼打上来多少,多少一斤?");
   return 2;
  }

 }
}

Zhang.cs

using System;

namespace delegateMain
{
 ///
 /// Zhang 的摘要说明。
 ///
 public class Zhang : IWorkerEvents
 {
  public void WorkStarted() {Console.WriteLine("张财主:打吧。(还没打渔就打电话啊)"); }
  public void WorkProgressing() { Console.WriteLine("张财主:打到鱼了再告诉我,烦不烦"); }
  public int WorkCompleted()
  {
   Console.WriteLine("张财主:老李你的鱼打上来多少,我要十斤?");
   return 20; /* 总分为10 */
  }
 }
}

FishMan.cs

using System;

namespace delegateMain
{
 ///
 /// FishMan 的摘要说明。
 ///
 public class FishMan
 {
  private IWorkerEvents _events;
  public FishMan()
  {
   //
   // TODO: 在此处添加构造函数逻辑
   //
  }
  public void Advise(IWorkerEvents events) { _events = events; }
  public void DoWork()
  {
   Console.WriteLine("渔夫老李: 尊敬的客户,我开始下网");
   if( _events != null ) _events.WorkStarted();

   Console.WriteLine("渔夫老李: 尊敬的客户,我正在打鱼中");
   if( _events != null ) _events.WorkProgressing();

   Console.WriteLine("渔夫老李: 尊敬的客户,我鱼打上来了");
   if( _events != null )
   {
    int grade = _events.WorkCompleted();
    Console.WriteLine("渔夫老李:卖得银两=" + grade);
   }
  }

 }
}

delegateMain.cs

using System;

namespace delegateMain
{
 ///
 /// Class1 的摘要说明。
 ///
 class FishManDemo
 {
  ///
  /// 应用程序的主入口点。
  ///
  [STAThread]
  static void Main(string[] args)
  {
   FishMan li = new FishMan();
   IWorkerEvents WangYuanWai = new Wang();
   IWorkerEvents Zhangcaizhu = new Zhang();
   li.Advise(Zhangcaizhu);
   li.DoWork();

   Console.WriteLine("Main: 打鱼完成");
   Console.ReadLine();

  }
 }
}

http://xiekeli.blogbus.com/files/1168047484.gif

http://xiekeli.blogbus.com/files/1168047589.gif

posted @ 2007-01-05 16:44  红心李  阅读(150)  评论(0编辑  收藏  举报