首页 > 代码库 > 随手复习一下委托:delegate

随手复习一下委托:delegate

先骂个街,天儿太闷了……

 

  随手复习一下委托,delegate 是一种函数指针,是 .net 提供的一种安全的函数指针,翻译的也很贴切,像是委托人,又像代理人,通过“委托”来执行一些函数而不是直接调用它。因为 C# 中委托被实现为指针链表,所以委托可以加入多个函数,一次性一块儿执行。

 

  举个花生:小明(中国教育中最频繁出镜的绝对明星,不知为什么,我脑子里直觉般闪现第一个名字就是它,我Kao)要给他妈买酱油(貌似这个例子在多年前我自己的帖子里出现过),妈妈对小明的调用就表示为:

1 public class 妈妈2 {3     酱油 Get酱油()4     {5         var 孩子 = new 小明();6         retu 小明.打酱油();7     }8 }
小明打酱油

当妈妈需要酱油时候,可以随时召唤小明去卖,那么如果需要盐呢、醋呢,假设 小明 都提供这样的方法,那么妈妈调用时候不得不这样:

 1 public class 妈妈 2 { 3     调料 Get调料() 4     { 5         var 多种调料 = new 调料集合(); 6         var 孩子 = new 小明(); 7         调料集合.Add(小明.打酱油()); 8         调料集合.Add(小明.买醋()); 9         调料集合.Add(小明.买盐());10         11         return 多种调料;12     }13 }
小明要买多种调料

事情到了现在,有两个很明显的问题:

1. 妈妈直接对小明进行了操作,这不是聪明的编码方式,因为如果妈妈还有闺女小红呢?让小红再去买东西就需要修改大量的妈妈类中的代码,显然很二。

2. 代码中规定了方法里只能调用小明三个技能,再多加两个或少买一个呢,就必须重新修改源代码了,所以不能做到动态的增减技能。

说到这里好像跑题去谈如何构建程序了,显然我还没到那个水平,回到委托,如果使用委托,至少可以同时解决这两个主要问题,因为:

1. 委托是“中间人”,妈妈可以全心关注对委托的控制,比如增加和减少要购买的东西

2. 委托是“相对抽象”的,妈妈通过委托既可以选择小明去买,也可以选择小红去买,一定程度上的解耦

 

用委托改一下,依旧忽略细节,只领会精神:

 1 public class 妈妈 2 { 3     delegate 调料 买调料委托(); 4     private 买调料委托 妈妈让孩子去买调料; 5 } 6  7 public static class 小明 8 { 9     public static 调料 打酱油(){}10     public static 调料 买醋(){}11     public static 调料 买盐(){}12 }13 14 public static class 小红15 {16     public static 调料 打酱油(){}17     public static 调料 买米(){}18     public static 调料 买油(){}19 }
妈妈用委托

妈妈定义了一个“买调料”的委托,只要孩子有和这个委托签名一致的技能,妈妈就可以使用。有了这个基础,妈妈再考虑买调料时候就人性化的多,比如 1 日要买酱油、醋和米,就可以这样:

1 妈妈让孩子去买调料 = new 买调料委托(小明.打酱油);2 妈妈让孩子去买调料 += 小明.买醋();3 妈妈让孩子去买调料 += 小红.买米();4 妈妈让孩子去买调料();
妈妈自由组合买东西

妈妈把分属于两个孩子的三个技能添加到了委托,妈妈只需要运行这个委托,就可以运行一次买到三个东西,2 日妈妈不再需要买米而需要买盐时,就可以这样:

1 妈妈让孩子去买调料 -= 小红.买米();2 妈妈让孩子去买调料 += 小红.买盐();
去掉米添上盐

从语法上来说我觉得已经比较人性化了,下面放上两个简单的示意代码,描述一下对委托的增减:

 1         delegate void OnEventDelegate(string text); 2         OnEventDelegate OnEventHandler; 3  4         private void button1_Click(object sender, EventArgs e) 5         { 6             if (OnEventHandler == null) 7             { 8                 OnEventHandler = new OnEventDelegate(ShowLabel1); 9                 OnEventHandler += ShowLabel2;10                 OnEventHandler += ShowLabel3;11                 OnEventHandler += ShowLabel4;12 13                 MessageBox.Show(string.Format("delegate object count: {0}", OnEventHandler.GetInvocationList().Count()));14             }15         }16 17         private void button2_Click(object sender, EventArgs e)18         {19             if (null != OnEventHandler)20             {21                 foreach (var method in OnEventHandler.GetInvocationList())22                 {23                     MessageBox.Show(string.Format("delegate has method cout: {0}, now remove : {1}", OnEventHandler.GetInvocationList().Count(), method.Method.Name));24 25                     OnEventHandler -= (OnEventDelegate)method;26 27                     if (null == OnEventHandler)28                     {29                         MessageBox.Show("delegate remove all method");30                         break;31                     }32                 }33             }34         }35 36         private void button3_Click(object sender, EventArgs e)37         {38             var timeString = DateTime.Now.Second.ToString();39             OnEventHandler(timeString);40         }
对委托的增减操作

 

完整示例点击下载