【设计模式】观察者模式

文章目录

  • 1.观察者模式定义
  • 2.观察者模式的角色
  • 3.观察者模式实战案例
    • 3.1.场景说明
    • 3.2.关系类图
    • 3.3.代码实现
  • 4.观察者模式优缺点
  • 5.观察者模式适用场景
  • 6.观察者模式总结

【设计模式】观察者模式_第1张图片

主页传送门: 传送

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张图片

2.观察者模式的角色

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

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

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

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

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

3.观察者模式实战案例

3.1.场景说明

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

3.2.关系类图

       使用观察者模式来实现的结构图如下:
【设计模式】观察者模式_第3张图片

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. 观察者
 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. 具体通知者
     前台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. 具体观察者
      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. 前台作为通知者进行通知(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. 老板作为通知者进行通知(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();
     }
     
 }

4.观察者模式优缺点

观察者模式的优点包括:

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

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

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

5.观察者模式适用场景

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

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

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

6.观察者模式总结

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

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

你可能感兴趣的:(设计模式,设计模式,观察者模式,java)