观察者模式与.NET的delegate、event机制
1.引言
最近在写一些程序玩的时候,接触到了delegate(委托)和event(事件),网上查找了很多的资料,有些博文说可以把delegate近似当做C++当中的函数指针来看,由于自己本身对C++的理解并不是很透彻,所以看得仍然朦朦胧胧。今天上课学习了设计模当中的观察者模式。仔细学习之下,又对委托和事件有了新的体悟,特分享给大家。也希望能够与各位大虾多多交流。
2.观察者模式介绍
2.1概述
观察者模式是建立一种对象与对象之间的依赖关系,一种对象发生改变时将自动通知其他对象,其他对象相应的做出反应。在观察者模式中,发生改变的对象称为观察目标,被通知对象称为观察者,一个观察目标可以对应多个观察者,而且这些观察者之间可以没有任何相互联系。就像在大街上,红灯亮起,来往的汽车停止,绿灯亮起,汽车可以继续前进,在这个过程中,交通信号是汽车的观察目标,大街上的汽车是观察者,并且大街上的每个汽车都是单独的个体没有相互之间的联系。
2.2观察者模式的定义
观察者模式:定义对象之间一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象都得到通知并被更新。
Observer Pattern: Define a one-to-manydependency between objects so that when one object changes state , all itsdependts are notified and update automatically.
2.3观察者模式结构
观察者模式包含以下四个角色:
(1)Subject(目标)
(2)ConcreteSubject(具体目标)
(3)Observer(观察者)
(4)ConcreteObserve(具体观察者)
2.4代码实例
using System.Collection //定义一个抽象目标类Subject abstract class Subject
{
//定义一个观察者集合用于存储所有观察者对象
protected ArrayList observers = new ArrayList(); //声明抽象注册方法,用于向观察者集合中增加一个观察者
public abstract void Attach(Observer observer); //声明抽象的注销方法,用于在观察者集合中删除一个观察者
public abstract void Detach(Oberver observer) //声明抽象通知方法
public abstract void Notify();
} //具体目标类ConcreteSubject 是实现了抽象目标类Subject的一个具体
//子类,它实现了上述的3中方法 class ConcreteSubject : Subject
{
public override void Attach(Observer observer)
{
observers.Add(observer);
} public override void Detach(Observer observer)
{
observers.Remove(observer);
} //实现通知方法
public override void Notify()
{
//遍历观察者几何,调用每一个观察者的相应方法
foreach (object obs in observers)
{
((Observer)obs).Update();
}
} /*抽象观察者一般定义为一个借口,通常只声明一个Update()方法
*为不同观察者的更新(相应)行为定义相同的借口,这个方法在其
*子类中实现。
*/
interface Observer
{
void Update();
} //具体观察者ConcreteObserver中实现Update()方法
class ConcreteObserver : Observer
{
//实现方法
public void Update()
{
//具体更新代码
}
}
static void Main(string[] args)
{
...
Subject subject = new ConcreteSubject();
Observer observer = new ConcreteObserver();
subject.Attach(observer);
subject.Notify();
...
}
}
3..NET中的delegate与event
.NET中的委托事件模型是观察者模式在.NET中的经典应用,在WinForm编程中需要编写时间处理程序对所发生的事件(例如鼠标单击、菜单项选取等)做出反应,并执行相应的操作。事件被触发后,并执行响应该事件的一个或多个事件处理程序,可以将一个事件对象(例如按钮、文本框、菜单等)成为事件的发送者(事件源对象),接收并响应事件的对象称为时间的接收者(事件处理对象)。与观察这模式相对应,事件源对象充当观察目标角色,事件处理对象充当具体观察者角色,如果事件源对象的某个事件触发,则调用事件处理对象中的事件处理程序对事件进行处理。
在.NETzhong ,如果需要从WinForm控件获取事件,提供一个委托(Delegate)类型的EventHandler,然后将它注册到事件源。在这里委托对象充当着抽象观察者的角色,所有事件处理方法都必须和委托方法具有相同的函数签名。
eventSource.someEvent += new SomeEventHandler(someMethod);
在该语法中,eventSource表示事件源,someEvent表示定义在事件源中的事件,someEventHandler表示用于处理事件的委托,someMethod表示与委托SomeEventHandler具有相同函数签名的事件处理方法。用户只需要修改someMethod,即可实现相同的时间对应不同的时间处理程序。
在.NET事件中,事件源并不需要知道哪些对象或方会受到将要发生的通知,它只持有与签名相符合的方法的引用,即委托;还可以通过多重传送事件来实现一个事件有过个订阅者,即通过委托将多个方法添加到该事件中,当该事件被触发时,同时执行对应的多个事件处理方法。
代码实例:
using System; namespace ObserverExtend
{
class EventTest
{
//定义一个委托
public delegate void UserInput(object sender, EventArgs e); //定义一个此委托类型的事件
public event UserInput OnUserInput; //模拟事件触发,当输入“0”时引发事件
public void Method()
{
bool flag = false;
Console.WriteLine("请输入数字:");
while(!flag)
{
if(Console.ReadLine() == "0")
{
OnUserInput(this ,new EventArgs());
}
}
}
} class Program
{
public Program(EventTest test)
{
//注册或订阅事件
test.OnUserInput += newEventTest.UserInput(Handler);
test.OnUserInput += newEventTest.UserInput(HandlerMore); //注销或取消订阅
//test.OnUserInput -= newEventTest.UserInput(Handler);
}
public void Handler(object sender,EventArgs e)
{
Console.WriteLine("数据输入结束!");
}
public void HandlerMore(object sender,EventArgs e)
{
Console.WriteLine("数据输入真的结束!");
} static void Main(string[] args)
{
EventTest test = new EventTest();
Program program = new Program();
tset.Method();
}
}
}
在Program的构造函数中订阅事件,在此处,通过委托将两个方法添加到事件中,即该事件有两个订阅者,当事件触发时同时触发这些方法的执行,Program类充当具体观察者角色,可以对目标类的事件作出响应,方法Handler()和HandlerMore() 即为响应方法。
4.感悟
设计模式的学习让我提升了不少对C#的理解,记得有句话,有抱负的开发人员还需大力发扬钻研精神,不拘泥与可视化软件实际带来的便利之处,深入理解相关的技术细节,这是初级开发人员的必由之路。我们要会的不仅仅是拖一个Button。加油,与君共勉~
5.参考资料
http://www.cnblogs.com/wangjq/archive/2012/07/12/2587966.html
《C#设计模式》刘伟 胡志刚 闫朝坤 清华大学出版社
观察者模式与.NET的delegate、event机制的更多相关文章
- C# delegate event func action 匿名方法 lambda表达式
delegate event action func 匿名方法 lambda表达式 delegate类似c++的函数指针,但是是类型安全的,可以指向多个函数, public delegate void ...
- [UE4] C++实现Delegate Event实例(例子、example、sample)
转自:http://aigo.iteye.com/blog/2301010 虽然官方doc上说Event的Binding方式跟Multi-Cast用法完全一样,Multi-Cast论坛上也有很多例子, ...
- [C#] Delegate, Multicase delegate, Event
声明:这篇博客翻译自:https://www.codeproject.com/Articles/1061085/Delegates-Multicast-delegates-and-Events-in- ...
- Delegate & Event
Long time without coding,貌似对programming都失去了曾有的一点点sense了,今日有空再细瞄一下.net的委托和事件. Delegate 首先,委托用于引用一类具有相 ...
- C# delegate & event
public delegate void MyDelegate(string mydelegate);//声明一个delegate对象 //实现有相同参数和返回值的函数 public v ...
- 深入理解jQuery的Event机制
jQuery的Event模块非常强大.其功能远远比原生事件监听器强大许多,对同一个元素的监听只用一个eventListener,内部则是一个强大的观察者,根据匹配事件类型触发相应回调.jQuery不仅 ...
- Delegate&Event
Delegate 1.基本类: public class Student { public int Id { get; set; } public string Name { get; set; } ...
- Delegate event 委托事件---两个From窗体使用委托事件
窗体如下: public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void b ...
- 委托与事件--delegate&&event
委托 访问修饰符 delegate 返回值 委托名(参数); public delegate void NoReturnNoPara(); public void NoReturnNoParaMeth ...
随机推荐
- Ubuntu释放磁盘空间的几种常用方法
一 安装stacer,使用它来清空系统内存 其实 Stacer 的安装步非常简单,只需到 Github 的发布页面下载到 .deb 包,再用 GDebi 或如下命令安装即可: wget https:/ ...
- 使用git在github上创建新工程
这段时间进经常会忘记如何在github上同步工程,于是又得查资料,查参考书,浪费了很长时间,因此有了感触,写几篇有关此类问题的篇章! 这是老手新手都十分容易犯的错误,就是在创建一个新github项目或 ...
- BeautifuSoup的使用
BeautifulSoup是一个模块,该模块用于接收一个HTML或XML字符串,然后将其进行格式化,之后遍可以使用他提供的方法进行快速查找指定元素,从而使得在HTML或XML中查找指定元素变得简单.
- 三方面搞定http协议之“请求方法”
我所熟知的请求方法一共有六种: GET 请求指定的页面信息,并返回实体主体. POST 向指定资源提交数据进行处理请求(例如提交表单或者上传文件) PUT 从客户端向服务器传送的数据取代指定的文档的内 ...
- java 容器 集合 用法
Set,List,Map,Vector,ArrayList的区别 JAVA的容器---List,Map,Set Collection ├List │├LinkedList │├ArrayList │└ ...
- ajax实现文档导出及下载
做导出一直遇到个问题就是不能用ajax实现一步导出文档,即导出加下载.今天突然想到可以分开来做就上网搜了下,发现一篇比较不错的文章(http://www.cnblogs.com/zj0208/p/59 ...
- MFC原理第三讲.RTTI运行时类型识别
MFC原理第三讲.RTTI运行时类型识别 一丶什么是RTTI RTTI. 运行时的时候类型的识别. 运行时类型信息程序.能够使用基类(父类)指针 或者引用 来检查这些指针或者引用所指的对象. 实际派生 ...
- SharePoint如何配置Ipad跳转等问题
如何配置Ipad跳转 Apple iPad 设备上不支持 SharePoint 标准视图.用户可以改用移动视图在 iPad 设备上查看 SharePoint 内容.默认情况下,iPad 用户被重定向到 ...
- Deep learning with Python 学习笔记(11)
总结 机器学习(machine learning)是人工智能的一个特殊子领域,其目标是仅靠观察训练数据来自动开发程序[即模型(model)].将数据转换为程序的这个过程叫作学习(learning) 深 ...
- 【Go】strings.Replace 与 bytes.Replace 调优
原文链接:https://blog.thinkeridea.com/201902/go/replcae_you_hua.html 标准库中函数大多数情况下更通用,性能并非最好的,还是不能过于迷信标准库 ...