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

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

结尾处有这样的问题:

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

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

1    public delegate void InputDelegate(int left, int right);

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

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

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

 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依然没问题.

 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类

 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,  把插排都弄没了, 让别的插头怎么办.

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

 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; 测试了一下 , 已经编译不通过了.

四. 小结

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏算法与数据结构

拓扑排序 ——个人理解,仅供参考

贴代码: #include <bits/stdc++.h> using namespace std; #define maxn 100//可以根据题目条件进行更...

2118
来自专栏大前端_Web

字符集和字符编码(Charset & Encoding)

计算机中储存的信息都是用二进制数表示的;而我们在屏幕上看到的英文、汉字等字符是二进制数转换之后的结果。通俗的说,按照何种规则将字符存储在计算机中,如’a’用什么...

3053
来自专栏恰童鞋骚年

《你必须知道的.NET》读书笔记一:小OO有大智慧

此篇已收录至《你必须知道的.Net》读书笔记目录贴,点击访问该目录可以获取更多内容。

602
来自专栏好好学java的技术栈

Java11震撼发布了,我们该怎么办?

Java11已经发布了,我们今天聊聊大家还停留在哪个版本呢?大家对于新版本的迅速的发布有什么想说的呢?

2072
来自专栏熊二哥

让我们一起写出更有效的CSharp代码吧,少年们!

周末空闲,选读了一下一本很不错的C#语言使用的书,特此记载下便于对项目代码进行重构和优化时查看。 Standing On Shoulders of Giant...

1885
来自专栏逍遥剑客的游戏开发

Nebula3学习笔记(3): 核心库

19911
来自专栏腾讯IVWEB团队的专栏

踩坑记:当 JavaScript 遇上 UINT 64

写下这篇文章的缘由是因为在项目过程中,碰到了一个使用 JavaScript 处理 UINT64 类型数字的坑。二进制浮点数中的 0.1 和 0.2 并不是十分...

7900
来自专栏chafezhou

小说python2和python3的差异

1934
来自专栏逍遥剑客的游戏开发

C++的反射和序列化

1632
来自专栏小樱的经验随笔

Codeforces 714A Meeting of Old Friends

A. Meeting of Old Friends time limit per test:1 second memory limit per test:256...

38410

扫码关注云+社区

领取腾讯云代金券