C# ~ 从 委托事件 到 观看者情势 – Observer

委托和事件的某个基础知识可参见 C#/.NET 基础学习 之 [委托-事件]
部分

参考
[1]. 初识事件 到
自定义事件

[2]. 从品种不安全的寄托 到
类型安全的轩然大波

[3]. 函数指针 ~
C#中的委托(Delegate)和事件(伊芙nt)

[4]. C# 中的委托和事件 –
张子阳

   C# 中的委托和事件(续) –
张子阳


委托

 委托本质是2个密封类,定义方法的品类,将艺术作为艺术的参数。委托包蕴二个负有相同签名和再次回到值类型的稳步的法门列表(调用列表)。
 委托注明:public delegate void MyDel(string str);
编写翻译结果为:

public sealed class MyDel : System.MulticastDelegate
{
   public MyDel(object @object, IntPtr method);
   public virtual void Invoke(string str);
   public virtual void EndInvoke(IAsyncResult res);
   public virtual IAsyncResult BeginInvoke(string str, AsyncCallback callback, object @object);
}

壮大:自定义委托类 MyDel 继承于类
MulticastDelegate,MulticastDelegate 类是 System.Delegate
的子类,辅助多路广播委托并敬爱对应的寄托列表。三个常用 public 属性:
 · Target:委托调用的章程所属的类实例的引用,若方法是静态方法,则为
null;
 · Method:委托所表示的格局的消息;
  构造函数中的参数:object 为指标实例的引用,methodPtr
用于标识回调方法,分别对应 Target 和 Method。二个常用 public 方法:
 · public Delegate[]
GetInvocationList();委托的调用列表中方法的数组;
参考:C# –
委托链
寄托的本质论; 

1. 创立委托(对象)

 [修饰符] delegate 返回值类型 MyDel(参数列表);
 MyDel objDel1 = new MyDel(obj.实例方法);   或 MyDel objDel1 = obj.实例方法;
 MyDel objDel2 = new MyDel(Class.静态方法); 或 MyDel objDel2 = Class.静态方法;

  · 为委托对象分配内部存款和储蓄器;
  · 把艺术添加到委托对象的调用列表中;

2. 组合委托 (Combining Delegate)

 委托是稳定的,委托对象被创制后就不会再被转移。委托组合拷贝的是操作数的副本,唯有相同类其他信托才足以整合。委托的结合和移除分别用”+”和”-“;

  MyDel objDel = objDel1 + objDel2; 

3. 调用委托

 objDel(参数列表); 或 objDel.Invoke(参数列表); 

  用于调用委托的参数会去调用调用列表中的每一种方法。
  · 调用带再次回到值的寄托:委托调用的重回值是其调用列表中最终八个方法的重临值。
  · 调用带引用参数的寄托:调用委托的参数会趁着调用列表中方法的调用而更改。
 :Invoke
是一块方法,BeginInvoke/EndInvoke 是异步方法,但其调用者 myDel
的调用列表有且不得不用1个措施,而 Invoke 没有那个范围。Invoke and
BeginInvoke
介绍

 IAsyncResult res = myDel.BeginInvoke(委托的参数列表, null, null);            
 myDel.EndInvoke(res);

4. 匿名委托

  匿名委托能够访问其所在艺术的一些变量,具体 .Net委托和事件 –
匿名委托部分

 

5. Action<> 和 Func<> 以及 Predicate<>

 
将委托的注明和赋值合并,进一步简化。Action<>没有重临值,Func<>有再次来到值。

  // 委托的几种赋值方法均可用在此处
  Func<int,bool> myDel = (Lambda表达式);
  Func<int,bool> myDel = new Func<int,bool>(函数名);

  Predicate<T> 是回来 bool 的泛型委托,能够驾驭为
Func<T,bool>的泛型委托的外号,多用来查询的标准化表明式。
 
 参考
 [1]. 从委托到匿名委托到拉姆da表明式再到
Action<>和Func<>

 [2].
浓密剖析委托与事件


事件

 参考:长远精通事件的黄山真面目
 对象一是事件发生者或发送者,对象二是事件接收者或订阅者,对象一产生新闻,对象二响应并拍卖音讯(事件/音信机制)。
 event 是 delegate 的高等级方式,事件封装了信托,委托封装了法子。事件涵盖3个私有委托,事件提供对个人控制委托的结构化访问,当事件触发时,调用委托来挨家挨户调用调用列表中的方法。在事变中,委托是事件的发起者
sender 将 伊夫ntArgs 传递给处理者的管道。

1. 事件注脚

 保存和调用事件处理程序。

public [static] event 委托类型 Notify; 

 推荐应用:事件选用正式的预约义委托类型

public delegate void EventHandler(object sender, EventArgs e); 

2. 事件注册格局

 ·  方法情势
  [1]. 实例方法:publisher.Notify += subscriber.实例方法;
  [2]. 静态方法:publisher.Notify += Subscriber.静态方法;
 ·  委托格局
  [1]. 实例方法:publisher.Notify += new 伊夫ntHandler(subscriber.实例方法);
  [2]. 静态方法:publisher.Notify += new 伊夫ntHandler(Subscriber.静态方法);
 ·  匿名方式
  publisher.Notify += delegate(object source, EventArgs args) { … };
 ·  Lambda表达式
  publisher.Notify += (source, args) => { … };
 :publisher
是公布者类对象;subscriber 是订阅者类对象,Subscriber 是订阅者类。

3. 事件访问器(Event Accessor)

 事件访问器表现为 void 方法,add 和 remove 访问器均含有隐式值参数
value。通过为事件证明自定义的轩然大波访问器,此时风云尚无内嵌委托对象,要求自定义添加和移除注册事件的艺术来自行封装1个信托的实例。事件的
add 和 remove 不能够缺且必须有落到实处核心但足以为空。

 private MyEventHandler notify = null;   /// [1] 声明委托的实例
 public event MyEventHandler Notify      /// [2] 事件封装委托的实例
 {
   add      /// 增加
   {
     if (null != value)
       notify += value;
   }
   remove   /// 删除
   {
     Delegate[] funList = notify.GetInvocationList();   /// 获取调用列表
     if (-1 != Array.IndexOf(funList, value))
       notify -= value;             
   }
 }

 参考
 [1]. 字段访问器 ~ 事件访问器 ~
索引器

 [2]. C#
事件访问器


函数指针 vs 委托

 回调函数,Callback,在函数体内调用主调用函数中的函数。
 · 函数指针:保存函数的输入地址,作为函数的参数、用于调用函数;
   委托:保存函数的输入地址同时保存调用该函数的类/类实例的引用;
 · 委托扩展性更好,辅助多播委托(MulitCast)和异步调用;

委托 vs 事件

 · 
委托扶助”+”和”-“、”+=”和”-=”、赋值运算符”=”;事件只是扶助”+=”和”-=”;
 ·  Delegate
是类(型),伊芙nt 是成员,伊夫nt 成员类型派生于 Delegate;
 · 
委托常用来抒发回调,事件宣布外发的接口;
 · 
委托:能够在类外部触发、允许直接通过信托调用相应的处理函数:委托对象(参数列表);
    事件:只辛亏类内部触发、通过揭橥者类提供的 public 方法去调用。
 :事件涵盖三个个体的委托对象。
事件的封装性和易用性更好。

 public MyEventHandler Notify1;
 public event MyEventHandler Notify2;

 其实,Notify1 相当于 Class 里面包车型地铁 字段Field,访问级别 public ,Notify2
相当于 属性Property,访问级别也是 public,可是,Notify2 内部封装了几个访问级别为 private 的 委托对象!(带 event
关键字,编写翻译之后,委托对象变成
private,并自动生成一个与信托对象对应的事件)
 属性封装字段,事件封装委托。
 图片 1 
 
 参考
 [1]. Event
详解

 [2]. 谈 C# 中的 delegate – hyddd –
博客园

 [3]. 不惧面试 –
关于信托
三个信托的例子


旁观者方式

 Observer Pattern,即 Subject-Observer,又称监听形式 (Source/Listener)
或 发布-订阅形式(Publisher-Subscriber),形式中的皇后。Observer
形式定义对象间的一(Subject)对多(Observer)的依赖关系,当一个指标意况改变时,注重于它的别的对象会被机关告知并立异。Observer
方式一对多将依靠具体转会为借助抽象,是一种松耦合的设计格局,但抽象类Subject还是借助于抽象类(接口)Observer。逻辑关系图:
图片 2
 :事件处理程序即被托付的办法。Observer
方式典例:报纸订阅、短信分发、电热水器,可参考 寄托和事件详解 –
补充

Java API 内置的观看者方式

  • java.util.Observable    — Subject 被观望者
  • java.util.Observer        — Observer 观察者

参考:

问题

  · 怎样界定事件只允许3个客户订阅?
 将事件证明为 private,然后提供七个 public
方法用于注册和打消。或利用事件访问器。
· 怎样获取多少个订阅者的重临值?
 利用 Delegate 类的静态方法 Delegate[]
GetInvocationList(),委托/事件变量调用之,然后遍历包罗委托方法的数组即可。

 

相关文章