• 设计模式


    观察者模式

    含义:定义了对象之间的一对多依赖关系,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并且自动更新。又称为“发布-订阅模式”

    实现过程:

    • 理论性:创建一个主题对象及多个订阅者,主题对象和订阅者之间形成一对多关系,当主题发生变化时,调用通知事件函数,使其订阅者做出相应改变
    • 比喻:居民订阅日报,报社每天将最新的报纸分发给订报者,订报者根据最新的报纸调整一天的形成,而没有订阅的人则无法享受该服务

    优缺点:

    • 优点:
      • 建立了 “主题-->多订阅者” 的事件机制
      • 使耦合双方依赖于抽象而不是具体(抽象耦合
    • 缺点:
      • 订阅者越多,主题通知用时越长,费时
      • 没有相应的机制让订阅者知道所订阅的对象是怎么发生变化的,仅仅知道变化了
      • 如果订阅者和主题对象间有循环依赖,可能导致系统崩溃

    适用场景:

    • 一个对象的改变将导致其他一个或多个对象也发生改变
    • 一个对象必须通知其他对象,而并不知道这些对象是谁
    • 触发反应机制

    项目示例:

    主题对象(布加拉提),订阅者(普罗修特、贝西),当布加拉提出现时,普罗修特和贝西做出各自反应:

    // 主题接口:
    // --------
    interface Subject
    {
        //添加/删除订阅者
        void Attach(Observer observer);
        void Detach(Observer observer);
    
        //通知事件
        void Notify();
    }
    
    // 具体主题:
    // --------
    class ConcreteSubject : Subject
    {
        // 订阅者清单
        private List<Observer> observers = new List<Observer>();
    
        public void Attach(Observer obs)
        {
            observers.Add(obs);
        }
    
        public void Detach(Observer obs)
        {
            if (observers.Contains(obs))
                observers.Remove(obs);
        }
    
        public void Notify()
        {
            //主题改变则通知其所有订阅者进行变化
            Console.WriteLine("出现了野生布加拉提!");
            foreach (Observer o in observers)
                o.Update();
        }
    }
    
    // 抽象订阅者:
    // ----------
    abstract class Observer
    {
        protected string name;
    
        public Observer(string name)
        {
            this.name = name;
        }
    
        // 各订阅者对通知事件的反应
        public abstract void Update();
    }
    
    // 具体订阅者:
    // ----------
    class ConcreteObserverA : Observer
    {
        public ConcreteObserverA(string name) : base(name) { }
    
        public override void Update()
        {
            Console.WriteLine($"{name} 发动替身: "The Grateful Dead!"");
        }
    }
    class ConcreteObserverB : Observer
    {
        public ConcreteObserverB(string name) : base(name) { }
    
        public override void Update()
        {
            Console.WriteLine($"{name} 发出呐喊:"普罗修特大哥!"");
        }
    }
    
    // 客户端:
    // ------
    class Client
    {
        static void Main(string[] args)
        {
            //创建主题对象(布加拉提)
            ConcreteSubject Bucciarati = new ConcreteSubject();
    
            //创建订阅者(普罗修特、贝西)
            ConcreteObserverA Prosciutto = new ConcreteObserverA("普罗修特");
            ConcreteObserverB Pesci = new ConcreteObserverB("贝西");
    
            //订阅者订阅主题对象
            Bucciarati.Attach(Prosciutto);
            Bucciarati.Attach(Pesci);
    
            //主题对象通知事件(布加拉提出现)
            Bucciarati.Notify();
    
    		/* OUT:
    			出现了野生布加拉提!
    			普罗修特 发动替身: "The Grateful Dead!"
    			贝西 发出呐喊:"普罗修特大哥!"
    		*/
        }
    }
    

    备注:

    除了上面的方法,C#中提供的 委托事件机制 也可较好实现观察者模式,该示例代码:观察者模式示例_委托版 - SouthBegonia's Github

    UML图

    参考

  • 相关阅读:
    SpringBoot/SpringMVC Restful接口全局异常处理
    spring/springboot/springmvc启用GZIP压缩
    centos7启动SonarQube 8.6报错
    类型初始值设定项引发异常
    OCI is not properly installed on this machine (NOE1/INIT)
    动态调用webservice 此 XML 文档中禁用 DTD。
    系统缺少插件 系统插件已过期
    几种常见的函数
    MQTT 协议基本介绍
    etcd:从应用场景到实现原理的全方位解读【修订版】
  • 原文地址:https://www.cnblogs.com/SouthBegonia/p/11984014.html
Copyright © 2020-2023  润新知