zoukankan      html  css  js  c++  java
  • 一个插排引发的设计思想 (三) 委托与事件

    一个插排引发的设计思想 (一) 观察者模式

    一个插排引发的设计思想 (二) 抽象类与接口

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

    ...待续....

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

    结尾处有这样的问题:

    无论是抽象类还是接口, 都是将设备本身放入了插排的集合中, 那么我们是否可以将此处的参数改为设备的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; 测试了一下 , 已经编译不通过了.

    四. 小结

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

  • 相关阅读:
    notepad++ remove duplicate line
    notepad++ $ ^
    中文名: 交通事故责任认定, 英文名称: Traffic accident responsibility identification
    java 反射 获取Class对象的三种方式
    [转]java中byte转换int时为何与0xff进行与运算
    java中byte取值范围为什么是 -128到127
    bytes2HexString
    DBCS 从256开始
    android开发之使用拼音搜索汉字
    电脑故障,路由器及网络
  • 原文地址:https://www.cnblogs.com/FlyLolo/p/8392848.html
Copyright © 2011-2022 走看看