示例代码为了尽可能突显设计模式的特征,采用了极简代码。尽量避免其他代码对理解设计模式产生干扰
定义
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
简而言之就是,观察者模式可以在被观察者的某个指定动作执行时,通知到其对应的观察者。使得观察者们可以即时做出相应的反应。
结构导图
示例项目简述
示例代码的大概意图其实就是实现一个下载器。当指定文件下载完成后,会通知其观察者们,以便这些观察者可以根据各自需求处理下载下来的文件。
接下来,请见具体代码。
代码
抽象观察者
/// <summary>
/// 抽象观察者
/// </summary>
interface IObserver
{
void DoUpdate();
}
其实这个抽象观察者,只是一个简单的接口。所有具体观察者都将继承自它。
具体观察者
/// <summary>
/// 具体观察者-文件下载完成后,备份文件。
/// </summary>
class Observer1 : IObserver
{
public void DoUpdate()
{
Console.WriteLine("观察者1已将文件备份。");
}
}
/// <summary>
/// 具体观察者-文件下载完成后,压缩文件。
/// </summary>
class Observer2 : IObserver
{
public void DoUpdate()
{
Console.WriteLine("观察者2已将文件压缩。");
}
}
/// <summary>
/// 具体观察者-文件下载完成后,发送文件。
/// </summary>
class Observer3 : IObserver
{
public void DoUpdate()
{
Console.WriteLine("观察者3已将文件发送给相关同事。");
}
}
以上是三个极简的具体观察者。它们分别在收到下载成功
的通知后,对文件进行备份,压缩及转发。
既然观察者们已经准备好了,那么该轮到被观察者了。
被观察者
一般,被观察者会相对复杂一点。因为它不单单要提供某动作的执行方法,也要提供注册及注销观察者的方法。
当一个被观察者被创建后,首先需要为其绑定一些其必需的观察者(如果需要的话)。观察者们被绑定成功后,这个观察者列表将被被观察者维护着。
若被观察者的某个动作执行完成后,如果需要通知观察者,那么就可以通过这个观察者列表,依次通知到所有需要被通知的观察者。
/// <summary>
/// 文件下载器-被观察者
/// </summary>
class Downloader
{
/// <summary>
/// 观察者列表
/// </summary>
public readonly HashSet<IObserver> observers;
public Downloader()
{
observers = new HashSet<IObserver>();
}
/// <summary>
/// 注册观察者
/// </summary>
public bool AddObserver(IObserver _observer)
{
return observers.Add(_observer);
}
/// <summary>
/// 注销观察者
/// </summary>
public bool RemoveObserver(IObserver _observer)
{
return observers.Remove(_observer);
}
/// <summary>
/// 下载
/// </summary>
public void Download()
{
Console.WriteLine("文件开始下载。");
Console.WriteLine("文件下载中···");
Thread.Sleep(3000);// 模拟文件下载的耗时过程
Console.WriteLine("文件下载完成。");
foreach (var observer in observers)
{
observer.DoUpdate();
}
}
}
如上代码中,当Download
方法内,文件下载成功后,就会遍历观察者列表,逐个通知对应的观察者,告诉它们:文件下载成功了,你该干嘛干嘛去
。
客户端
请看客户端代码
// 实例化下载器
var downloader = new Downloader();
// 创建观察者
var o1 = new Observer1();
var o2 = new Observer2();
var o3 = new Observer3();
// 注册观察者
downloader.AddObserver(o1);
downloader.AddObserver(o2);
downloader.AddObserver(o3);
// 下载
downloader.Download();
创建一个被观察者对象,然后为其注册三个观察者。注册成功后,就可以执行下载文件的动作了。
当文件下载完成后,Download
方法内部会自行通知已经成功注册的观察者们。
运行结果
如你所见,当文件下载完成
的通知发出后,各个观察者就开始了它们各自的小动作,分别是备份,压缩,转发。
总结
由于观察者们本身就有一个公共的抽象观察者,这样在某个观察者需要变动时,大可以废弃掉这个观察者,另起一个新的观察者,而不用去对现有的任何观察着做任何改动。因此从这个角度上讲,观察者模式是符合开闭原则的。
以上就是极简版的观察者模式的全部内容了。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。