11委托演绎中国足球队打进世界杯

当针对不同的类型采取相同的算法时,我们想到了泛型。当根据相同的参数列表,采取不同的算法时,我们可以考虑使用委托。就用委托演绎中国男足进入2018年世界杯吧。


对球的不同处理方式,抽象成如下方法:

   1:          private static void PassBall(string ball)
   2:          {
   3:              Console.Write("传" + ball);
   4:          }
   5:   
   6:          private static void StopBall(string ball)
   7:          {
   8:              Console.Write("停/接" + ball);
   9:          }
  10:   
  11:          private static void TransferpBall(string ball) 
  12:          {
  13:              Console.Write("转移" + ball);
  14:          }
  15:   
  16:          private static void RunBall(string ball)
  17:          {
  18:              Console.Write("带" + ball);
  19:          }
  20:   
  21:          private static void ScoreBallByHead(string ball)
  22:          {
  23:              Console.Write("头"+ball + "射门");
  24:          }
  25:   
  26:          private static void ScoreBallByInnerFeet(string ball)
  27:          {
  28:              Console.Write("推射" + ball + "射门");
  29:          }
  30:   
  31:          private static void ScoreBallByOuterFeet(string ball)
  32:          {
  33:              Console.Write("外脚背射" + ball + "门");
  34:          }

发现尽管方法名,方法体内的实现逻辑不一样,但参数列表是一样的,都是针对球的,委托登场。

public delegate void PlayBall(string ball);

委托从本质上来讲就是一个类,所以也可以把委托作为方法参数。

        private static void Game(string ball, PlayBall playBallDelegate)
        {
            playBallDelegate(ball);
        }

主程序中先把各种方法注册到委托,然后在Game方法中使用不同的委托所代表的方法,控制球的处理。

   1:          static void Main(string[] args)
   2:          {
   3:              PlayBall del;
   4:              del = PassBall;
   5:              del += StopBall;
   6:              del += TransferpBall;
   7:              del += RunBall;
   8:              del += ScoreBallByHead;
   9:              del += ScoreBallByInnerFeet;
  10:              del += ScoreBallByOuterFeet;
  11:   
  12:              string str = "欢迎大家来到中国队进军2018年俄罗斯世界杯的生死战,本场比赛,中国队只有获胜才能拿到世界杯的入场券,比赛进行到90分钟,中国队与韩国队的比分依然是0:0,补时3分钟。最后关头,小伙子们加油啊!";
  13:   
  14:              Console.WriteLine(str);
  15:              Console.WriteLine();
  16:              Console.WriteLine();
  17:   
  18:              Console.Write("中后卫冯潇霆");
  19:              Game("球",PassBall);
  20:              Console.Write("给了队长郑智");
  21:              Console.WriteLine();
  22:   
  23:              Console.Write("郑智");
  24:              Game("球",TransferpBall);
  25:              Console.Write("给了右边路后插上的张琳芃");
  26:              Console.WriteLine();
  27:   
  28:              Console.Write("张琳芃");
  29:              Game("球",RunBall);
  30:              Console.Write("过了韩国队2名后卫,把球交给了张稀哲");
  31:              Console.WriteLine();
  32:   
  33:              Console.Write("张稀哲稳稳地");
  34:              Game("球",StopBall);
  35:              Console.Write(",把球交给了无人防守的武磊");
  36:              Console.WriteLine();
  37:   
  38:              Console.Write("武磊");
  39:              Game("",ScoreBallByOuterFeet);
  40:              Console.Write(",韩国队守门员奋力扑出");
  41:              Console.WriteLine();
  42:   
  43:              Console.Write("球落到了左边路孙祥的脚下");
  44:              Console.Write(",孙祥传中");
  45:              Console.WriteLine();
  46:   
  47:              Console.Write("后点郜林");
  48:              Game("球",ScoreBallByHead);
  49:              Console.Write(", 球进了!");
  50:              Console.WriteLine();
  51:              Console.WriteLine();
  52:              Console.WriteLine();
  53:              Console.WriteLine("进了!进了!进了!伟大的中国队前锋!他继承了中国队光荣的传统。郝海东、李金羽、高峰在这一刻灵魂附体!郜林一个人他代表了中国足球悠久的历史和传统,在这一刻他不是一个人在战斗,他不是一个人! ");
  54:              Console.ReadKey();
  55:          }

 

结果:
1

 

□ 委托也可以不使用+=

PlayBall del1 = PassBall;
PlayBall del2 = StopBall;    
Game("球",del1);   
Game("球",del2);   

 

□ 委托赋值是用=,委托绑定是用+=,两者不能混淆

如果以上来就:
PlayBall del1 += PassBall;  
这样会报"使用了未赋值的局部变量"错,因为委托变量还没有赋值,正所谓"皮之不存毛将焉附"。

 

□ 可以通过带参数的委托构造函数为委托变量赋值

PlayBall del1 = new PlayBall(PassBall);
del1 += StopBall;

 

□ 不可以通过不带参数的委托构造函数为委托变量赋值

PlayBall del1 = new PlayBall();
这样会报"没有0个参数的重载"的错。

 

□ 也可以取消委托中的某个方法的绑定

PlayBall del1 = new PlayBall(PassBall);
del1 += StopBall;
del1 += ScoreBallByHead;
del1 -= StopBall;

 

□ 接口与委托

共同点:

隔离了变化。

 

不同点:
接口不仅参数列表一样,方法名也一样。
接口可能更适合单元测试。

 

体验:
可能在小范围之内,使用委托比较好。
一旦涉及到分层、扩展、单元测试,可能使用接口比较好。

 

参考资料:
《.NET之美》--张子阳,感谢写了这么好的书!

你可能感兴趣的:(11委托演绎中国足球队打进世界杯)