观察者模式【C#】

示例代码为了尽量突显设计模式的特征,采用了极简代码。尽可能避免其余代码对理解设计模式产生干扰

定义

定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,全部依赖于它的对象都获得通知并被自动更新。
简而言之就是,观察者模式能够在被观察者的某个指定动做执行时,通知到其对应的观察者。使得观察者们能够即时作出相应的反应。

结构导图

观察者模式导图


示例项目简述

项目结构

示例代码的大概意图其实就是实现一个下载器。当指定文件下载完成后,会通知其观察者们,以便这些观察者能够根据各自需求处理下载下来的文件。c#

接下来,请见具体代码。设计模式

代码

抽象观察者

/// <summary>
/// 抽象观察者
/// </summary>
interface IObserver
{
    void DoUpdate();
}

其实这个抽象观察者,只是一个简单的接口。全部具体观察者都将继承自它。spa

具体观察者

/// <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已将文件发送给相关同事。");
    }
}

以上是三个极简的具体观察者。它们分别在收到下载成功的通知后,对文件进行备份压缩转发设计

既然观察者们已经准备好了,那么该轮到被观察者了。code

被观察者

通常,被观察者会相对复杂一点。由于它不仅仅要提供某动做的执行方法,也要提供注册及注销观察者的方法。
当一个被观察者被建立后,首先须要为其绑定一些其必需的观察者(若是须要的话)。观察者们被绑定成功后,这个观察者列表将被被观察者维护着。
若被观察者的某个动做执行完成后,若是须要通知观察者,那么就能够经过这个观察者列表,依次通知到全部须要被通知的观察者。server

/// <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方法内,文件下载成功后,就会遍历观察者列表,逐个通知对应的观察者,告诉它们:文件下载成功了,你该干吗干吗去对象

客户端

请看客户端代码blog

// 实例化下载器
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方法内部会自行通知已经成功注册的观察者们。继承

运行结果

程序运行结果

如你所见,当文件下载完成的通知发出后,各个观察者就开始了它们各自的小动做,分别是备份,压缩,转发。接口

总结

因为观察者们自己就有一个公共的抽象观察者,这样在某个观察者须要变更时,大能够废弃掉这个观察者,另起一个新的观察者,而不用去对现有的任何观察着作任何改动。所以从这个角度上讲,观察者模式是符合开闭原则的。
以上就是极简版的观察者模式的所有内容了。

相关文章
相关标签/搜索