C# ~ 从 委托事件 到 观察者格局 – Observer

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

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

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

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

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

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


委托

 委托本质是一个密封类,定义方法的档次,将艺术作为艺术的参数。委托包含一个有所相同签名和再次回到值类型的静止的章程列表(调用列表)。
 委托声明: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
的调用列表有且只可以用一个方法,而 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>的泛型委托的别名,多用来查询的条件表明式。
C#, 
 参考
 [1]. 从委托到匿名委托到兰姆(Lamb)da表达式再到
Action<>和Func<>

 [2].
深深解析委托与事件


事件

 参考:深入领会事件的本色
 对象一是事件暴发者或发送者,对象二是事件接收者或订阅者,对象一发生消息,对象二响应并拍卖音信(事件/音信机制)。
 event 是 delegate 的高档格局,事件封装了信托,委托封装了主意。事件涵盖一个私家委托,事件提供对私有控制委托的结构化访问,当事件触发时,调用委托来挨家挨户调用调用列表中的方法。在事变中,委托是事件的发起者
sender 将 伊夫(Eve)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 伊夫(Eve)ntHandler(subscriber.实例方法);
  [2]. 静态方法:publisher.Notify += new 伊夫ntHandler(Subscriber.静态方法);
 ·  匿名形式
  publisher.Notify += delegate(object source, EventArgs args) { … };
 ·  Lambda表达式
  publisher.Notify += (source, args) => { … };
 :publisher
是公布者类对象;subscriber 是订阅者类对象,Subscriber 是订阅者类。

3. 事件访问器(伊芙(Eve)nt Accessor)

 事件访问器表现为 void 方法,add 和 remove 访问器均含有隐式值参数
value。通过为事件讲明自定义的轩然大波访问器,此时事件没有内嵌委托对象,需要自定义添加和移除注册事件的办法来自行封装一个寄托的实例。事件的
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,并自动生成一个与信托对象对应的轩然大波)
 属性封装字段,事件封装委托。
 C# 1 
 
 参考
 [1]. Event
详解

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

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


观望者情势

 Observer Pattern,即 Subject-Observer,又称监听情势 (Source/Listener)
或 公布-订阅形式(Publisher-Subscriber),形式中的皇后。Observer
情势定义对象间的一(Subject)对多(Observer)的倚重性关系,当一个目的情况改变时,倚重于它的其他对象会被活动告知并革新。Observer
形式一对多将凭借具体转会为借助抽象,是一种松耦合的设计格局,但抽象类Subject依然凭借于抽象类(接口)Observer。逻辑关系图:
C# 2
 :事件处理程序即被托付的艺术。Observer
格局典例:报纸订阅、短信分发、热水器,可参考 寄托和事件详解 –
补充

Java API 内置的寓目者格局

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

参考:

问题

  · 咋样界定事件只同意一个客户订阅?
 将事件注明为 private,然后提供五个 public
方法用于注册和撤除。或采用事件访问器。
· 怎样收获五个订阅者的重临值?
 利用 Delegate 类的静态方法 Delegate[]
GetInvocationList(),委托/事件变量调用之,然后遍历包含委托方法的数组即可。

 

相关文章