前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【设计模式 10】观察者模式

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

作者头像
JuneBao
发布2022-10-26 14:59:13
2690
发布2022-10-26 14:59:13
举报
文章被收录于专栏:JuneBaoJuneBao

观察者模式又叫发布订阅模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时会通知所有观察者对象,使它们能够自动更新自己。

观察者模式

观察者模式又叫发布订阅模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时会通知所有观察者对象,使它们能够自动更新自己。 参考:

有时需要在对象和对象之间建立一种一对多的联系,使得某个对象(频道/目标)发生改变时,能够通知其他对他感兴趣的对象(订阅者/观察者)使之能够及时根据目标的变化更新自己的状态。

组成:

目标(Subject):它是具体目标的一个抽象,有时可以只有具体目标,一般包含一个用来保存所有订阅(观察)此目标的容器以及添加删除订阅者的方法和通知所有订阅者的方法

代码语言:javascript
复制
public abstract class Subject {
    private Set<Observer> observers = new HashSet<>();

    void addObserver(Observer observer) {
        observers.add(observer);
    }

    void delObserver(Observer observer){
        observers.remove(observer);
    }

    /**
     * 通知所有订阅者
     */
    void noticeAll() {
        for (Observer observer : observers) {
            observer.update();
        }
    }

}

具体目标(ConcreteSubject): 目标的具体实现

观察者(Observer):具体观察者的抽象,一般是一个接口,接口中至少有一个当目标发生变化后更新自己的方法。

代码语言:javascript
复制
public interface Observer {
    void update();
}

具体观察者(ConcreteObserver):观察者的具体实现。

代码语言:javascript
复制
public class ConcreteObserver implements Observer {
    @Override
    public void update() {
        System.out.println("更新了");
    }
}
UTOOLS1590158692083.png
UTOOLS1590158692083.png

使用场景

  • 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
  • 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
  • 一个对象必须通知其他对象,而并不知道这些对象是谁。
  • 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制

实例:

MVC模式是一种架构模式,它包含三个角色:模型(Model),视图(View)和控制器(Controller)。观察者模式可以用来实现MVC模式,观察者模式中的观察目标就是MVC模式中的模型(Model),而观察者就是MVC中的视图(View),控制器(Controller)充当两者之间的中介者(Mediator)。当模型层的数据发生改变时,视图层将自动改变其显示内容。

优缺点

优点:

  1. 符合开闭原则,引入新的订阅者无需修改发布者代码
  2. 可以在运行时动态建立对象之间的联系
  3. 支持广播
  4. 观察者模式可以实现表示层和数据逻辑层的分离,并定义了稳定的消息更新传递机制,抽象了更新接口,使得可以有各种各样不同的表示层作为具体观察者角色。
  5. 观察者模式在观察目标和观察者之间建立一个抽象的耦合。

缺点:

  1. 如果观察者和目标存在循环订阅,可能导致系统崩溃
  2. 观察者只能知道目标变换了,不知道目标怎么变化的
  3. 如果观察者和目标之间存在多个观察者,这样消息传递会很费时
  4. 通知顺序可能是随机的

Java对观察者模式的支持

Java util包中提供了 Observer接口和Observable类,前者就是观察者接口,后者相当于目标 Subject,实现具体目标时可以继承该类。

代码语言:javascript
复制
public interface Observer {
    void update(Observable o, Object arg);
}
  • 相比自己定义的Observer接口, 官方的update方法多了两个参数,第一个参数是被观察者(目标)的一个引用,第二个参数是目标发生变化时调用notifyObservers方法时传递过来的。

Observable类中定义的方法和上面的Subject类似,但是它做了更完整的的并发控制,并且使用了一个布尔变量changed标识目标是否被修改,并使用setChanged()CleanChanged()两个方法控制这个变量,只有这个变量是true时,才会通知所有观察者,通知完后重新置为false,所以如果要让自己的方法调用时通知所有观察者,需要调用setChanged()

不同的顾客可以订阅不同的电视频道,电视频道发布新电视时,通知所有订阅者

代码语言:javascript
复制
import java.util.Observable;

public class CCTV1 extends Observable {
    public void release(){
        this.setChanged();
        this.notifyObservers();
    }
}
代码语言:javascript
复制
import java.util.Observable;
import java.util.Observer;

public class Customer implements Observer {
    @Override
    public void update(Observable o, Object arg) {
        System.out.println( o.getClass().getSimpleName() + " 发布新节目");
    }
}
代码语言:javascript
复制
public class Client {
    public static void main(String[] args) {
        CCTV1 cctv1 = new CCTV1();
        Customer customer1 = new Customer();
        // 顾客1订阅CCTV1
        cctv1.addObserver(customer1);
        cctv1.release();
    }
}

GitHub | 完整代码

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-5-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 观察者模式
    • 使用场景
      • 优缺点
        • Java对观察者模式的支持
          相关产品与服务
          容器服务
          腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档