初步了解事件
- 定义: 单词Event,译为“事件”
- 《牛津词典》中的解释是“a thing that happens,especially something important”
- 通顺的解释就是“能够发生的什么事情”
- 角色: 使对象或类具备通知能力的成员
- (中译)事件(Event)是一种使对象或类能够提供通知的成员
- (原文)An event is a member that enables an object or class to provide notifications.
- “对象O拥有一个事件E”想表达的思想是:当事件E发生的时候,O有能力通知别的对象
- 使用: 用于对象或类间的动作协调与信息传递(消息推送)
- 原理: 事件模型(event model)中的两个“5”
- “发生→响应”中的5个部分——闹钟响了你起床、孩子饿了你做饭…这里隐含着“订阅”关系
- “发生→响应”中的5个动作——(1)我有一个事件→(2)一个人或一群人关心我的这个事件→(3)我的这个事件发生了→(4)关心这个事件的人会被依次通知到→(5)被通知到的人根据拿到的事件信息(又称“事件数据”、“事件参数”、“通知”)对事件进行响应(又称“处理事件”)。
- 提示
- 事件多用于桌面、手机等开发的客户端编程,因为这些程序经常是用户通过事件来“驱动”的
- 各种编程语言对这个机制的实现方法不尽相同
- Java语言里没有事件这种成员,也没有委托这种数据类型。Java的“事件”是使用接口来实现的
- MVC、MVP、MVVM等模式,是事件模式更高级、更有效的“玩法”
- 日常开发的时候,使用已有的事件的机会比较多,自己声明事件的机会比较少,所以先学使用
事件的应用
- 事件模型的五个组成部分
1.事件的拥有者(event source,对象)
2.事件成员(event,成员)
3.事件的响应者(event subscriber,对象)
4.事件处理器(event handler,成员)——本质上是一个回调方法
5.事件订阅——把事件处理器与事件关联在一起,本质上是一种以委托类型为基础的“约定”
例子:
class Program
{
static void Main(string[] args)
{
Timer timer = new Timer();
//timer 事件拥有者
timer.Interval = 1000;
Boy boy = new Boy();
Girl girl = new Girl();
//boy,Girl 事件响应者
timer.Elapsed += boy.Action;
timer.Elapsed += girl.Action;
//+= 事件订阅操作符,Elapsed 事件,Action 事件处理器
//光标在Action处,按alt+Enter,生成事件处理器
timer.Start();
Console.ReadLine();//使程序停在这里,让我们看程序运行的结果
}
}
class Boy
{
internal void Action(object sender, ElapsedEventArgs e)
//此处的Action事件处理器为C#自动生成
{
Console.WriteLine("Jump!");
}
}
class Girl
{
internal void Action(object sender, ElapsedEventArgs e)
{
Console.WriteLine("Sing!");
}
}
标准的事件机制模型:
class Program
{
static void Main(string[] args)
{
Form form = new Form(); //事件拥有者
Controller controller = new Controller(form); //事件响应者
form.ShowDialog();
}
}
class Controller
{
private Form form;
public Controller(Form form)
{
if (form!=null)
{
this.form = form;
this.form.Click += this.FormClicked;
//为form.Click添加(挂接)事件处理器
}
}
private void FormClicked(object sender, EventArgs e)
{
this.form.Text = DateTime.Now.ToString();
}
}
事件对象用自己的方法订阅自己的事件:
class Program
{
static void Main(string[] args)
{
MyForm form = new MyForm(); //事件拥有者和响应者为同一对象
form.Click += form.FormClicked;
form.ShowDialog();
}
}
class MyForm : Form
//派生:一个类即包含自己写的新代码,又保留原来某个类的所有功能;在原有某个类的基础上扩展新的功能
{
internal void FormClicked(object sender, EventArgs e)
{
this.Text = DateTime.Now.ToString();
}
}
组合结构:事件拥有者是事件响应者的一个字段成员,事件响应者用自己的方法订阅了自己字段成员的某个事件。
//点击按钮,文本框显示“Hello World!”
class Program
{
static void Main(string[] args)
{
MyForm form = new MyForm();
form.ShowDialog();
}
}
class MyForm : Form //MyForm的对象 事件响应者
{
private TextBox textBox;
private Button button; //button 事件拥有者,Form的字段成员
public MyForm()
{
this.textBox = new TextBox();
this.button = new Button();
this.Controls.Add(this.button);
this.Controls.Add(this.textBox);
this.button.Click += this.ButtonClicked; //订阅
this.button.Top = 30;
this.button.Text = "Click Me!";
}
private void ButtonClicked(object sender, EventArgs e)
{
this.textBox.Text = "Hello World!";
}
}
- 注意
- 事件处理器是方法成员
- 挂接事件处理器的时候,可以使用委托实例,也可以直接使用方法名,这是个“语法糖”
- 事件处理器对事件的订阅不是随意的,匹配与否由声明事件时所使用的委托类型来检测
- 事件可以同步调用也可以异步调用