初步了解事件
事件的自然语意:能够发生的事,能以“发生”为谓语的东西
C#中定义:一个对象或类的成员,使这个对象或类具备通知能力
“响铃这个事件,使手机具备了通知关注这个手机的人的能力”
在事件发生时,关注者通过收到的通知,能得到和事件相关的一些信息(称作事件参数)
关注者会去检查收到的事件信息(事件参数),然后根据其内容采取相应行动(称作响应/处理)
处理事件时具体做的事称作事件处理器
有一些事件只有通知,没有事件参数,他们的通知本身已经够关注者采取行动了
比如看见红灯亮(通知)→踩刹车(响应)
警报响起(通知)→往外跑(响应)
所以事件参数不是必须的
有事件参数的事件:
手机响起(通知)→看手机,发现收到开会的信息(事件参数)→前往会议室(响应)
事件的功能:
用于对象或类间的动作协调与信息传递
一个对象可以通过事件通知其他的对象,其他对象收到消息以后做出响应
事件是对现实世界逻辑的一个模拟
事件模型
五大要素:事件、关注、通知、事件参数、响应(处理事件)
我的闹钟响我会起床→说明我关注着这个闹钟
我的孩子饿了我归做法→说明我关注着这个孩子
事件模型中包含一种“订阅(关注)”关系
通知顺序
事件发生时,关注这个事件的人会被依次通知到
通知的顺序就是他们订阅这个事件的顺序,先订阅的先被通知
同义术语约定
事件的订阅者
== 事件的响应者 == 事件的处理者 == 被事件所通知的对象
事件参数
== 事件信息 == 事件消息 == 事件数据 == 事件参数
事件的拥有者、事件的源头source
== 事件的主体 == 事件消息的发送者
事件的应用场合
多用于客户端程序
用户操作控件(如鼠标键盘)时,对应控件的事件就会被触发
通过订阅事件,可以让各个类来响应(处理)事件,用户就会看到响应的结果,称作一次事件循环
将用户戳一下动一下,不戳就不动的程序,称作事件驱动程序
事件驱动程序在客户端开发中具有统治地位
事件模型是从现实世界中抽象出来的客观存在,各种编程语言都可以实现,但实现方式的细节不同
相关设计模式
事件模式本身就是一种设计模式
但事件模式也有缺陷,事件牵扯的元素特别多,有五大要素
使用时若不加规划,很可能使程序逻辑混乱
为使合作者保持一致,将具有同类功能的代码写在固定地方
经过长期实践,总结出了几种最佳解决方案,MVC、MVP、MVVN等几种程序架构模式
日常工作中绝大部分时候都在使用C#已经准备好的事件,很少使用自定义事件
C#自带事件详见下一节
事件五大要素
1.事件的拥有者
事件的拥有者,英文enent source 事件的源头
拥有者一定是一个对象或类
2.事件本身
对于拥有者来说,事件是一个用来通知外部的工具
事件不会自发地发生,只有当事件的拥有者完成某个内部逻辑,事件才会被动地激活,通知订阅者
如按钮被按下时,操作系统会通过按钮的内部逻辑激活事件,然后按钮事件通知相关对象
被点击时,按钮的内部逻辑会检测到按下与松开的操作连续进行
按钮就会使用click点击事件来通知订阅了点击事件的对象,然后事件的订阅者开始响应
(程序在事件的驱动下运行)
3.事件的订阅者(响应者)
事件订阅者者就是订阅(关注)了这个事件的对象或类
4.事件的响应
响应者会使用自己的方法成员来处理事件(该方法称作事件处理器)
事件处理器是一个回调方法
5.事件的订阅
将事件处理器与事件拥有者关联在一起,本质上是一种以委托类型为基础的“约定”
事件处理器和事件本身必须遵守同样的约定,确保其匹配,需要一种强力的耦合
在C#中这个约定就是委托
事件的响应者类中可能有很多方法,可能响应事件需要同时使用其中多个方法
订阅事件时会告诉事件当其发生时用哪些方法去响应
五大要素的一些组合方式
1.拥有者与响应者 相互独立
称作标准事件模型
事件的拥有者与事件的响应者相互独立
2.拥有者与响应者 同为一体
一个类或对象用自己的方法订阅了自己的事件
3.响应者为[父] 拥有者为[子]
拥有者是响应者的成员,响应者包含拥有者
如准备写一个UI界面
按钮(子)是UI界面的成员,是事件的拥有者
响应事件的方法写在UI界面(父)的程序中,用来响应按钮的事件
这是windows平台上代代相传的默认事件处理结构
实例演示
事件的拥有者的成员中会有图标为小闪电的成员
这种小闪电标记的就是事件成员
小扳手是属性,小方块是方法,小闪电是事件
属性表示对象处于的状态,方法表示对象能做什么,事件表示能在什么情况下通知谁
这是一个类、对象最重要的三个功能
如何订阅事件
使用操作符 += ,在后面写上要订阅这个事件的事件处理器方法
运行结果:程序每一秒打印一个Jump
多个处理器订阅同一个事件
创建第二个事件处理器,打印sing!
运行结果:jump和sing会同时打印出来,打印顺序依照订阅的顺序,先订阅的先打印
1.分体组合方式
2. 同体组合方式
一个对象用自己的方法订阅处理自己的事件
3.拥有者是响应者的成员
事件是挂接在作为成员的按钮上
但事件处理器是写在按钮的拥有者类中
使用实例化委托来订阅事件
除了直接使用"+=方法名"订阅方法
还可以使用+= 生成委托实例,再往委托实例里塞方法(使用委托的构造函数)
使用匿名委托订阅事件(已废弃)
是拉姆达表达式的前身,原地定义一个没有名字的方法作为事件处理器
使用拉姆达表达式订阅事件
是现在流行的原地定义方法作为事件处理器的写法
甚至可以不写参数的数据类型,C#会自动推断他们的类型
非常的方便简单
这些都说明事件背后的委托
unity中的UI按钮、动画事件就是使用的事件
显然,可以事件可以挂接多个处理器,一个处理器也可以被多个事件挂接