事件与观察者模式
C#
中的事件
是一种典型的观察者模式
在winform
程序中,可订阅按钮等控件引发的事件。
事件具有以下属性(来自MicrosoftDoc):
- 发行者确定何时引发事件;订户确定对事件作出何种响应。
- 一个事件可以有多个订户。 订户可以处理来自多个发行者的多个事件。
- 没有订户的事件永远也不会引发。
- 事件通常用于表示用户操作,例如单击按钮或图形用户界面中的菜单选项。
- 当事件具有多个订户时,引发该事件时会同步调用事件处理程序。 若要异步调用事件,请参阅 Calling Synchronous Methods Asynchronously。
- 在 .NET Framework 类库中,事件基于 EventHandler 委托和 EventArgs 基类。
示例
以下是参照张阳-博客园-三种观察者模式的C#实现的示例
智能闹钟例子
闹钟响铃后,打开床头灯,打开窗帘,播放音乐。
闹钟相关方法
private void TurnOnTheAlarm(DateTime? alarmTime)
{
if (!alarmTime.HasValue)
{
return;
}
var cancelToken = new CancellationTokenSource();
var task = new Task(() =>
{
while (!cancelToken.IsCancellationRequested)
{
if (DateTime.Now >= alarmTime.Value)
{
// 闹铃时间到了
Alarm();
cancelToken.Cancel();
}
else
{
logger.Info($"现在时间是:{DateTime.Now}");
}
cancelToken.Token.WaitHandle.WaitOne(TimeSpan.FromSeconds(1));
}
}, cancelToken.Token, TaskCreationOptions.LongRunning);
task.Start();
}
private void Alarm()
{
AlarmClock alarmClock = new AlarmClock();
BedsideLamp turnOnTheBedsideLamp = new BedsideLamp(logger, "床头灯", alarmClock);
Curtains curtains = new Curtains(logger, "窗帘", alarmClock);
Speaker speaker = new Speaker(logger, "音响", alarmClock);
alarmClock.DoSomething("闹钟响了,准备起床。");
}
闹钟类及相关事件
/// <summary>
/// 闹钟类
/// </summary>
public class AlarmClock
{
public event EventHandler<CustomEventArgs> AlarmCustomEvent;
public void DoSomething(string s)
{
OnAlarmCustomEvent(new CustomEventArgs(s));
}
protected virtual void OnAlarmCustomEvent(CustomEventArgs e)
{
EventHandler<CustomEventArgs> handler = AlarmCustomEvent;
if (handler != null)
{
//e.Message += $" at {DateTime.Now}";
handler(this, e);
}
}
}
public delegate void EventHandler(object sender, EventArgs e);
public class CustomEventArgs : EventArgs
{
public CustomEventArgs(string s)
{
message = s;
}
private string message;
public string Message
{
get { return message; }
set { message = value; }
}
}
订阅闹钟的设备
/// <summary>
/// 床头灯
/// </summary>
public class BedsideLamp
{
private string id;
private Logger _logger;
public BedsideLamp(Logger logger, string ID, AlarmClock pub)
{
_logger = logger;
id = ID;
pub.AlarmCustomEvent += HandleCustomEvent;
}
void HandleCustomEvent(object sender, CustomEventArgs e)
{
_logger.LogImportantInfo($"【{id}】 收到消息: {e.Message}");
_logger.LogImportantInfo($"【{id}】 已打开床头灯");
}
}
/// <summary>
/// 窗帘
/// </summary>
public class Curtains
{
private string id;
private Logger _logger;
public Curtains(Logger logger, string ID, AlarmClock pub)
{
_logger = logger;
id = ID;
pub.AlarmCustomEvent += HandleCustomEvent;
}
void HandleCustomEvent(object sender, CustomEventArgs e)
{
_logger.LogImportantInfo($"【{id}】 收到消息: {e.Message}");
_logger.LogImportantInfo($"【{id}】 已打开窗帘");
}
}
/// <summary>
/// 音箱
/// </summary>
public class Speaker
{
private string id;
private Logger _logger;
public Speaker(Logger logger, string ID, AlarmClock pub)
{
_logger = logger;
id = ID;
pub.AlarmCustomEvent += HandleCustomEvent;
}
void HandleCustomEvent(object sender, CustomEventArgs e)
{
_logger.LogImportantInfo($"【{id}】 收到消息: {e.Message}");
_logger.LogImportantInfo($"【{id}】 开始播放音乐");
}
}