前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一个插排引发的设计思想 (三) 委托与事件

一个插排引发的设计思想 (三) 委托与事件

作者头像
FlyLolo
发布2018-05-17 15:19:49
5020
发布2018-05-17 15:19:49
举报
文章被收录于专栏:Core NetCore Net

前两篇文章循序渐进的介绍了观察者模式、抽象类和接口, 并分析了抽象类和接口的不同.

结尾处有这样的问题:

无论是抽象类还是接口, 都是将设备本身放入了插排的集合中, 那么我们是否可以将此处的参数改为设备的Input方法呢?

那么我们就用到了委托Delegate.

代码语言:javascript
复制
1    public delegate void InputDelegate(int left, int right);

看到接下来的代码, 老鸟别笑, 请允许我"循序渐进"的引导着思路重构.

我们用委托InputDelegate定义了插头的标准. 那么原来的代码改变一下

一. 用方法作为参数传递, 代替原来的整个设备

代码语言:javascript
复制
 1     public delegate void InputDelegate(int left, int right);
 2     public class OutPut
 3     {
 4         public OutPut()
 5         {
 6             this.EACollection = new List<InputDelegate>();
 7         }
 8         private List<InputDelegate> EACollection;
 9         public void powered(int left, int right)
10         {
11             foreach (var item in EACollection)
12             {
13                 item(left, right);
14             }
15         }
16         public void AddInput(InputDelegate item)
17         {
18             EACollection.Add(item);
19         }
20 
21         public void RemoveInput(InputDelegate item)
22         {
23             EACollection.Remove(item);
24         }
25     }
26 
27     class Program
28     {
29         static void Main(string[] args)
30         {
31             OutPut op = new OutPut();
32             op.AddInput(new TV().Input);
33             op.AddInput(new ElectricKettle().InputAAAA);
34 
35             op.powered(220, 0);
36 
37             Console.ReadKey();
38         }
39     }

原来的TV和ElectricKettle无需任何继承任何抽象类和接口, 只要有和定义的Delegate一样的方法签名的方法即可.

甚至名字都可以不一样, 例如ElectricKettle的input方法我随便改了一下改成了InputAAAA依然没问题.

代码语言:javascript
复制
 1     public class ElectricKettle
 2     {
 3         public void InputAAAA(int left, int right)
 4         {
 5             Heat();
 6         }
 7 
 8         private void Heat()
 9         {
10             Console.WriteLine("I am heating");
11         }
12     }

通过上面的方法, 我们把插入插排的参数由整个设备改成了设备的插头. 

功能是实现了, 但Delegate用起来没必要那么麻烦, 我们继续改

二. 用+=和-=来操作

我们改造一下Output类

代码语言:javascript
复制
 1     public delegate void InputDelegate(int left, int right);
 2     public class OutPut
 3     {
 4         public InputDelegate inputDelegate;
 5         public void powered(int left, int right)
 6         {
 7             inputDelegate(left, right);
 8         }
 9     }
10 
11     class Program
12     {
13         static void Main(string[] args)
14         {
15             OutPut op = new OutPut();
16             op.inputDelegate += new TV().Input;
17             op.inputDelegate += new ElectricKettle().InputAAAA;
18 
19             op.powered(220, 0);
20 
21             Console.ReadKey();
22         }
23     }

简洁多了, 根据Delegate的特性, 插排集本身也被inputDelegate代替了.

在调用的时候, 我们只需将input方法 +=到该inputDelegate即可.

三. 委托和事件

上面的例子貌似已经很好了, 但既然是插排, 也就是可能会有好多插头来插拔, 而插头之间互不干涉, 调用的位置可能存在于系统的任何位置 .

但上面的代码让我们想到一个问题,

我们把"集和"暴露出来了, 之前的 private List<IGBElectricalable> EACollection是私有的, 只可以通过add和 remove两个方法操作.

现在我们把它public了,  哪个捣蛋的写了一句op.inputDelegate = null,  把插排都弄没了, 让别的插头怎么办.

所以我们还希望像原来那样只提供增减的方法, 不允许赋值, 这里我们就用到了事件.

代码语言:javascript
复制
 1     public delegate void InputDelegate(int left, int right);
 2     
 3     public class OutPut
 4     {
 5         public event InputDelegate inputEvent;
 6         public void powered(int left, int right)
 7         {
 8             inputEvent(left, right);
 9         }
10     }
11 
12     class Program
13     {
14         static void Main(string[] args)
15         {
16             OutPut op = new OutPut();
17             
18             op.inputEvent += new TV().Input;
19             op.inputEvent += new ElectricKettle().InputAAAA;
20             //op.inputEvent = null;
21             op.powered(220, 0);
22 
23             Console.ReadKey();
24         }
25     }

Output中的 inputDelegate 改为了 inputEvent, inputEvent不再允许通过=来赋值了.

main方法中注释的一行 //op.inputEvent = null; 测试了一下 , 已经编译不通过了.

四. 小结

本文通过委托, 将方法作为参数注册到了插排中.  因为安全问题, 又将委托改为了事件.

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-02-01 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一. 用方法作为参数传递, 代替原来的整个设备
  • 二. 用+=和-=来操作
  • 三. 委托和事件
  • 四. 小结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档