• 【设计模式】观察者模式



    在这里插入图片描述

    主页传送门:💁 传送

    1.观察者模式定义

           观察者模式(Observer Pattern)是对象的行为模式,又叫发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。其定义如下:

    Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

           即:定义对象之间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。
           其通用类图如下:
    在这里插入图片描述

    2.观察者模式的角色

    观察者模式所涉及的角色有:

    • 抽象主题(Subject)角色:
      抽象主题角色把所有对观察者对象的引用保存在一个聚集(比如ArrayList对象)里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象,抽象主题角色又叫做抽象被观察者(Observable)角色。

    • 具体主题(ConcreteSubject)角色:
      将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色又叫做具体被观察者(Concrete Observable)角色。

    • 抽象观察者(Observer)角色:
      为所有的具体观察者定义一个接口,在得到主题的通知时更新自己,这个接口叫做更新接口。

    • 具体观察者(ConcreteObserver)角色:
      存储与主题的状态自恰的状态。具体观察者角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态 像协调。如果需要,具体观察者角色可以保持一个指向具体主题对象的引用。

    3.观察者模式实战案例

    3.1.场景说明

           下面举一个具体实例,假设上班时间有一部分同事在看股票,一部分同事在看NBA,这时老板回来了,前台通知了部分同事老板回来了,这些同事及时关闭了网页没被发现,而没被通知到的同事被抓了个现行,被老板亲自“通知”关闭网页

    3.2.关系类图

           使用观察者模式来实现的结构图如下:
    在这里插入图片描述

    3.3.代码实现

    1. 通知者接口
    public interface Subject {
     
         //增加
         public void attach(Observer observer);
         //删除
         public void detach(Observer observer);
         //通知
         public void notifyObservers();
         
         //状态
         public void setAction(String action);
         public String getAction();
         
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    1. 观察者
     public abstract class Observer {
     
         protected String name;
         protected Subject subject;
         
         public Observer(String name, Subject subject) {
             this.name = name;
             this.subject = subject;
         }
         
         public abstract void update();
         
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    1. 具体通知者
       前台Secretary和老板Boss作为具体通知者,实现Subject接口。这里只给出Secretary类的代码,Boss类与之类似。
    
     public class Secretary implements Subject {
    
        //同事列表
         private List<Observer> observers = new LinkedList<>();
         private String action;
     
         //添加
         @Override
         public void attach(Observer observer) {
             observers.add(observer);
         }
     
         //删除
         @Override
         public void detach(Observer observer) {
             observers.remove(observer);
         }
     
         //通知
         @Override
         public void notifyObservers() {
             for(Observer observer : observers) {
                 observer.update();
             }
         }
     
         //前台状态
         @Override
         public String getAction() {
             return action;
         }
     
         @Override
         public void setAction(String action) {
             this.action = action;
         }
         
     }
    
    • 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
    1. 具体观察者
        StockObserver是看股票的同事,NBAObserver是看NBA的同事,作为具体观察者,继承Observer类。这里只给出StockObserver类的代码,NBAObserver类与之类似。
     public class StockObserver extends Observer {
         
         public StockObserver(String name, Subject subject) {
             super(name, subject);
         }
     
         @Override
         public void update() {
             System.out.println(subject.getAction() + "\n" + name + "关闭股票行情,继续工作");
         }
     
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    1. 前台作为通知者进行通知(Client)
        前台作为通知者,通知观察者。这里添加adam和tom到通知列表,并从通知列表中删除了adam,测试没在通知列表中的对象不会收到通知。
     public class Client {
     
         public static void main(String[] args) {
             //前台为通知者
             Secretary secretary = new Secretary();
             
             StockObserver observer = new StockObserver("adam", secretary);
             NBAObserver observer2 = new NBAObserver("tom", secretary);
             
             //前台通知
             secretary.attach(observer);
             secretary.attach(observer2);
             
             //adam没被前台通知到,所以被老板抓了个现行
             secretary.detach(observer);
             
             //老板回来了
             secretary.setAction("小心!Boss回来了!");
             //发通知
             secretary.notifyObservers();
         }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    1. 老板作为通知者进行通知(Client)
        老板作为通知者,通知观察者。这里将tom从老板的通知列表中移除,老板只通知到了adam
     public class Client {
     
         public static void main(String[] args) {
             //老板为通知者
             Boss boss = new Boss();
             
             StockObserver observer = new StockObserver("adam", boss);
             NBAObserver observer2 = new NBAObserver("tom", boss);
             
             //老板通知
             boss.attach(observer);
             boss.attach(observer2);
             
             //tom没被老板通知到,所以不用挨骂
             boss.detach(observer2);
             
             //老板回来了
             boss.setAction("咳咳,我大Boss回来了!");
             //发通知
             boss.notifyObservers();
         }
         
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    4.观察者模式优缺点

    观察者模式的优点包括:

    • 解耦:观察者模式有效地解耦了主题和观察者之间的依赖关系,主题不再需要直接管理观察者,而观察者也不再需要了解主题的具体实现。
    • 抽象:观察者模式让耦合的双方都依赖于抽象,提高了系统的可扩展性和可维护性。
    • 通知:观察者模式可以支持多种通知方式,包括异步通知,这样可以提高系统的效率和性能。

    然而,观察者模式也存在一些缺点:

    • 开发复杂:观察者模式需要实现三个接口(主题,观察者和通知),并编写相应的代码,这增加了开发和维护的复杂性。
    • 顺序执行:观察者模式的通知是顺序执行的,如果有一个观察者的操作失败了,可能会影响到其他观察者的执行。
    • 状态共享:观察者模式需要共享主题的状态,如果主题的状态是复杂的,或者多个观察者的状态之间存在依赖关系,那么这可能会导致开发和维护变得更加复杂。

    5.观察者模式适用场景

    观察者模式适用于以下场景:

    1. 发布-订阅系统:这是观察者模式最经典的用途。在这种场景中,发布者发布消息并通知所有已订阅该消息的订阅者。观察者模式可以用来实现这种通知机制。
    2. GUI开发:在图形用户界面开发中,当用户与界面交互时,观察者模式可以用来通知其他组件。例如,当用户点击按钮时,可以自动更新相关的其他组件。
    3. MVC模式:在MVC模式中,当模型发生变化时,视图会自动更新。这种机制可以通过观察者模式来实现。具体来说,当模型对象状态改变时,所有依赖于它的视图都会接收到通知并自动更新。

    除了以上场景,观察者模式还适用于任何需要实现一对多依赖关系的场景。

    6.观察者模式总结

         观察者模式是一种设计模式,用于在对象之间建立一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种模式在许多领域都有广泛的应用,如GUI开发、事件处理、状态管理等。
         总的来说,观察者模式在某些情况下可以非常有用,但是也需要根据实际需求来考虑其适用性。在实际开发中,我们可以使用观察者模式来实现新闻推送、消息广播等需求,以提高代码的可维护性和可扩展性。

    如果喜欢的话,欢迎 🤞关注 👍点赞 💬评论 🤝收藏 🙌一起讨论
    你的支持就是我✍️创作的动力! 💞💞💞

  • 相关阅读:
    Docker 启动容器报错:cannot allocate memory: unknown
    Lua-http库写一个爬虫程序怎么样 ?
    MyBatis Like 拼接
    C语言——深入理解指针——函数指针
    今日伦敦金行情怎样分析?
    Js与Jq实战:第三讲:JavaScript对象编程
    【论文基本功】【LaTeX】个人常用易忘LaTeX命令
    【salesforce】Lightning Web Component Study Log —— Part 2
    java计算机毕业设计小区物业管理系统源程序+mysql+系统+lw文档+远程调试
    实用的窗口管理软件:Display Maid for Mac
  • 原文地址:https://blog.csdn.net/hm973046/article/details/133200917