为了按时完成某事,常常需要闹铃提醒我们当前时间。没有闹铃存在,为了能够准确把握时间,要求我们频繁去观察钟表,即便如此,也经常会错过时间。这里我们创造一个事件案例,实现时钟可以时刻提醒人当前时间。
在自定义事件时,我们需要明确谁是订阅者(subscriber),谁是发布者(publisher),谁是客户端(client)。在这个案例中,时钟可以发布时间,供人观察,因此他是发布者,在观察者设计模式中也被称为监视对象;而人就是订阅者,即监视者。这里的客户端是指触发事件的类,例如本案例中Program类Main函数。
自定义一个事件,需要为不同角色规划不同工作。例如
- 发布者需要拥有事件触发方法OnEventName、以及一个事件
- 订阅者需要拥有与事件参数、返回值类型匹配的事件处理程序
- 客户端需要将订阅者事件处理程序注册到发布者定义的事件中,并触发OnEventName
注:注册过程不一定总是出现在客户端。
反之,如何解读一个事件,即判断每一部分的角色。
- 定义事件触发方法OnEventName的是发布者。
- 触发OnEventName的客户端。
- 在事件注册过程中很容易判断订阅者,因为订阅者的事件处理程序总是需要被注册到事件中。
namespace EventExample
{
//一、声明一个事件处理委托(委托对象名称以EventHandler结尾)
public delegate void TimeChangedEventHandler(object obj, TimeEventArgs args);
//二、在事件发送者中完成事件定义、事件触发方法编写
class Clock
{
//定义一个"TimeChanged"事件,注意其前面有两个关键字"event"和"TimeChangedEventHandler"
public event TimeChangedEventHandler? TimeChanged;
public Clock()
{
}
//事件触发函数,我们的目标是每秒钟触发一次TimeChanged事件
public void GoTime()
{
DateTime init = DateTime.Now;
int h1 = init.Hour;
int m1 = init.Minute;
int s1 = init.Second;
while (true)
{
DateTime now = DateTime.Now;
int h2 = now.Hour;
int m2 = now.Minute;
int s2 = now.Second;
if (s2 != s1)
{
h1 = h2;
m1 = m2;
s1 = s2;
//首先建立一个TimeEventArgs对象来保存相关参数,这里是时分秒
TimeEventArgs args = new TimeEventArgs(h2, m2, s2);
//注意这种写法,这一句是用来触发事件,事件不是类,所以不用使用"new"关键字,而且我们看到,这里TimeChanged的两个参数跟我们的委托(TimeChangedEventHandler)是一致的
//其中第一个参数是触发这个事件的对象,我们这里使用的是一个时钟实例(this)
if (this.TimeChanged != null)
{
this.TimeChanged(this, args);
}
}
}
}
}
//三、观察者类,定义"委托"的方法也就是某事件发生后跟进的某些事件处理程序
//也就是void KnowTime(object obj,TimeEventArgs args)
//从这个方法的定义可以看到,我们只会关心返回类型和方法的参数,而方法名称则无所谓
class HardWorker
{
public void KnowTime(object obj, TimeEventArgs args)
{
Console.WriteLine("现在时间:" + args.Hour + ":" + args.Minute + ":" + args.Second);
}
}
class Program
{
static void Main(string[] args)
{
Clock clock = new Clock(); //实例化一个事件发送者-时钟
HardWorker worker1 = new HardWorker(); //实例化一个观察者类-打工人
//四、将打工人的事件处理程序knowTime注册到钟表的事件中
clock.TimeChanged += new TimeChangedEventHandler(worker1.KnowTime);
//五、在客户端中触发事件
clock.GoTime();
}
}
//TimeEventArgs是我们自己定义的一个类,用于保存事件中的参数.这里我们分别保存时间的时分秒
public class TimeEventArgs : EventArgs
{
private int hour;
private int minute;
private int second;
public TimeEventArgs(int hour, int minute, int second)
{
this.hour = hour;
this.minute = minute;
this.second = second;
}
public int Hour
{
get
{
return this.hour;
}
}
public int Minute
{
get
{
return this.minute;
}
}
public int Second
{
get
{
return this.second;
}
}
}
}
代码运行结果如下: