• 设计模式之观察者模式(Observer)


    1. 简介

    观察者模式允许你定义一种订阅机制,可在对象事件发生时,通知多个 “观察” 该对象的其他对象

    在这里插入图片描述

    1.1 作用

    观察者模式定义的是一种一对多的关系:

    • 一是主题类,多是观察者类
    • 当主题类的状态发生改变时,会通知与之对应的观察者类,去相应地更新状态
    • 支持动态增加、删除观察者类对象

    解决的问题

    • 如下图所示,每次到货都要发邮件给各家各户
      在这里插入图片描述

    • 用观察者模式解决问题:商店浪费资源去通知没有需求的客户
      在这里插入图片描述

    优缺点

    ✔ 优点❌ 缺点
    无需修改发布者代码就能引入新的订阅者类 (如果是发布者接口则可轻松引入发布者类)订阅者的通知顺序是随机的
    可以在运行时建立对象之间的联系

    1.2使用场景

    • 当应用中一些对象必须观察其他对象时,可用观察者模式,但仅能在有限的复杂度或特定情况下使用
    • 当一个对象状态的改变需要改变其他对象, 或实际对象是事先未知的或动态变化的时, 可使用观察者模式

    2. 实现

    2.1 UML 图

    在这里插入图片描述

    2.2 代码

    Program:

    namespace Observer
    {
        class Program
        {
            static void Main(string[] args)
            {
                Subject subject = new Subject();
                ObserverA observerA = new ObserverA();
                ObserverB observerB = new ObserverB();
    
                subject.Attach(observerA);
                subject.Attach(observerB);
    
                subject.SomeBusinessLogic();
                subject.SomeBusinessLogic();
    
                subject.Detach(observerA);
    
                subject.SomeBusinessLogic();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    IObserver:

    namespace Observer
    {
        interface IObserver
        {
            public void Update(ISubject subject) { }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    ObserverA:

    using System;
    
    namespace Observer
    {
        class ObserverA: IObserver
        {
            public void Update(ISubject subject)
            {
                if ((subject as Subject).state > 2)
                {
                    Console.WriteLine("ObserverAAA Update ... state: " + (subject as Subject).state.ToString());
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    ObserverB:

    using System;
    
    namespace Observer
    {
        class ObserverB:IObserver
        {
            public void Update(ISubject subject)
            {
                if((subject as Subject).state > 0 && (subject as Subject).state < 3)
                {
                    Console.WriteLine("ObserverBBB Update ... state: " + (subject as Subject).state.ToString());
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    ISubject:

    namespace Observer
    {
        interface ISubject
        {
            public void Attach(IObserver observer) { }
            public void Detach(IObserver observer) { }
            public void Notify() { }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    Subject:

    
    using System;
    using System.Collections.Generic;
    using System.Threading;
    
    namespace Observer
    {
        class Subject: ISubject
        {
            public int state;
            private List<IObserver> observerList = new List<IObserver>();
    
            public void Attach(IObserver observer) 
            {
                if (observer != null)
                {
                    observerList.Add(observer);
                }
            }
    
            public void Detach(IObserver observer) 
            {
                if (observer != null)
                {
                    observerList.Remove(observer);
                }
            }
    
            public void Notify()
            {
                foreach (var observer in observerList)
                {
                    observer.Update(this);
                }
            }
    
            public void SomeBusinessLogic()
            {
                Console.WriteLine("Subject do SomeBusinessLogic");
                state = new Random().Next(0, 10);
    
                Thread.Sleep(15);
                Console.WriteLine("Subject SomeBusinessLogic state: " + state.ToString());
    
                Notify();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    F5 运行结果:

    Subject do SomeBusinessLogic
    Subject SomeBusinessLogic state: 8
    ObserverAAA Update … state: 8
    Subject do SomeBusinessLogic
    Subject SomeBusinessLogic state: 0
    Subject do SomeBusinessLogic
    Subject SomeBusinessLogic state: 1
    ObserverBBB Update … state: 1

    参考:观察者模式

  • 相关阅读:
    pandas merge 和 concat
    GD32F103ZET6奋斗者开发板W5500通信——01 基础移植
    Codeforces Round #779 (Div. 2)
    GEE——自GLDAS-2.0 每日流域模型批量导出逐月Terrestrial water storage水存量影像下载
    RHEL 7配置HAProxy实现Web负载均衡
    python爬虫爬取电影数据并做可视化
    Redis数据类型-Set-基本使用
    使用matlab产生二维动态曲线视频文件具体举例
    CentOS8安装SystemTap小记
    MySQL、Oracle、SQL Server / MS Access 中的 NULL函数用法
  • 原文地址:https://blog.csdn.net/qq_36804363/article/details/126395751