观察者模式(Observer):在对象间定义一种 一对多 的依赖关系,以便当某对象的状态改变时,与它存在依赖关系的所有对象都能收到通知并自动进行更新。

  • MVC 模式的底层可以说就是利用了观察者模式

# 基础设计

我们可以使用如下的方式设计一个简单的观察者模式,在被观察者中需要存储一个观察者组,提供一个发送消息的方法对观察组进行消息推送。

在观察者中提供一个消息响应的方法,响应消息。

事件
/// <summary>
    /// 事件
    /// </summary>
    public enum Event
    {
        捡到金币,
        通关
    }
接口
/// <summary>
    /// 观察者接口
    /// </summary>
    public interface IObserver
    {
        /// <summary>
        /// 接收通知
        /// </summary>
        /// <param name="subject"></param>
        /// <param name="eventMsg"></param>
        void OnNotify(Subject subject, Event eventMsg);
    }
    /// <summary>
    /// 被观察者接口
    /// </summary>
    public interface ISubject
    {
        List<IObserver> Observers();
        void AddObserver(IObserver observer);
        void RemoveObserver(IObserver observer);
    }
实体对象
/// <summary>
    /// 观察者
    /// </summary>
    public class Observer : IObserver
    {
        public void OnNotify(Subject subject, Event eventMsg)
        {
            switch (eventMsg)
            {
                case Event.捡到金币:
                    subject.Score += 10;
                    break;
                case Event.通关:
                    subject.Score += 100;
                    break;
            }
        }
    }
    /// <summary>
    /// 被观察者
    /// </summary>
    public class Subject : ISubject
    {
        public int Score;
        private readonly List<IObserver> _observers;
		
        /// <summary>
        /// 发送消息
        /// </summary>
        /// <param name="eventMsg"></param>
        public void Notify(Event eventMsg)
        {
            _observers.ForEach(x=>x.OnNotify(this,eventMsg));
        }
        
        public Subject()
        {
            _observers = new List<IObserver>();
        }
        public List<IObserver> Observers()
        {
            return _observers;
        }
        public void AddObserver(IObserver observer)
        {
            _observers.Add(observer);
        }
        public void RemoveObserver(IObserver observer)
        {
            _observers.Remove(observer);
        }
    }

# 使用委托和事件

在 Csharp 中内置了委托和事件来处理这种一对多的响应方式。

c#内置了委托和事件
using System;
namespace ObserverPattern
{
    /// <summary>
    /// 观察者模式
    /// </summary>
    internal static class Program
    {
        
        public static void Main(string[] args)
        {
            var c = new Cat() {Name = "小白"};
            var m = new Mouse(c) {Name = "小鼠"};
            c.OnCatCom();
        }
    }
    class Cat
    {
        public string Name { get; set; }
        public event Action catCom;
        public virtual void OnCatCom()
        {
            Console.WriteLine("{0}来了",Name);
            catCom?.Invoke();
        }
    }
    class Mouse
    {
        public string Name { get; set; }
        public Mouse(Cat cat)
        {
            // 将事件绑定到方法
            cat.catCom += this.MouseRun;
        }
        private void MouseRun()
        {
            Console.WriteLine("{0}快跑!!",Name);
        }        
    }
}

# 思考

其实观察者模式就是对象的一种 间接同步调用 ,使用这种方法是为了解除耦合,达到统一分配管理的作用。

从上文提到的可以知道,这种模式是同步的,也就是说当存在一组观察者时,那么可能会导致 阻塞 ,但在实际中可能没这么严重,但在使用中我们还需注意。

如果你在每次响应后给出一个状态,表示通知的响应情况,那么这就接近 责任链模式 了。

# 销毁对象?

在书中提到一个问题很有趣,在观察者模式中销毁对象该怎么办呢?

在销毁对象前,需要解除监听,确保对象被正确销毁。

# 现状

观察者模式出现于 1994 年(比我还大😄), 因此基本都是基于类来实现的,但现在更流行 函数式编程 ,可能不太符合现在的编程美学。例如 C# 的 event 就是现代化的观察者模式。

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

Fasty 微信支付

微信支付

Fasty 支付宝

支付宝

Fasty 贝宝

贝宝