【设计模式】详解观察者模式

文章目录

1、简介

观察者模式是一种行为型设计模式,它定义了一种一对多的依赖关系,当一个对象的状态发生改变时,它的所有依赖者都会收到通知并自动更新。(MQ和它有点像)

当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知依赖它的对象。观察者模式属于行为型模式。

观察者模式中,一共有四种角色:

  1. Subject(抽象主题):也称为被观察者或可观察者,它是具有状态的对象,并维护着一个观察者列表。抽象主题角色把所有观察者对象保存在一个集合里,每个主题都可以有任意数量的观察者。主题提供了添加、删除和通知观察者的方法。一般用一个抽象类或者一个接口实现
  2. Observer(抽象观察者):为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。这个接口叫做更新接口。抽象观察者角色一般用一个抽象类或者一个接口实现。在这个示意性的实现中,更新接口只包含一个方法(即Update()方法),这个方法叫做更新方法。
  3. ConcreteSubject(具体主题):也可称为具体被观察者,该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知。
  4. ConcrereObserver(具体观察者):实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自身的状态。如果需要,具体现察者角色可以保存一个指向具体主题对象的引用。

从具体主题角色指向抽象观察者角色的合成关系,代表具体主题对象可以有任意多个对抽象观察者对象的引用。之所以使用抽象观察者而不是具体观察者,意味着主题对象不需要知道引用了哪些ConcreteObserver类型,而只知道抽象Observer类型。这就使得具体主题对象可以动态地维护一系列的对观察者对象的引用,并在需要通知的时候调用每一个观察者共有的update()更新方法。这种做法叫做"针对抽象编程"。

2、观察者模式简单实现

拿博客专栏订阅为例,网站用户的博客专栏为被观察者,用户为观察者,当有多个用户关注了yhz的JVM专栏,当yhz的JVM专栏更新时就会通知这些订阅的用户。

抽象主题(Subject)

java 复制代码
package DesignModel.Observer;

import java.util.ArrayList;

/**
 * @BelongsProject: 3.9.demo
 * @Author: yhz
 * @CreateTime: 2023-07-26  17:58
 * @Description: TODO
 * @Version: 1.0
 */
public abstract class Subject {
    //定义一个订阅者集合用于存储所有订阅了这个专栏的用户对象
    protected ArrayList<Observer>observers = new ArrayList();
    //注册方法,用于向订阅者集合中增加一个订阅者
    public void attach( Observer observer ) {
        observers.add( observer );
    }
    //注销方法,用于在订阅者集合中删除一个订阅者
    public void detach( Observer observer ) {
        observers.remove( observer );
    }
    //通知所有订阅者更新消息
    public abstract void notifyObservers(String message);
}

具体主题(ConcreteSubject)

yhz的这个专栏为具体主题,里面存储了订阅该专栏的网站用户,并实现了抽象主题中的通知方法:

java 复制代码
package DesignModel.Observer;

/**
 * @BelongsProject: 3.9.demo
 * @Author: yhz
 * @CreateTime: 2023-07-26  18:18
 * @Description: TODO
 * @Version: 1.0
 */
public class ConcreteSubject extends Subject{

    //重写通知方法为自己的
    @Override
    public void notifyObservers(String message) {
        //通知订阅了该主题的所有订阅者
        for(Observer observer:observers){
            observer.update(message);
        }
    }
}

抽象观察者(Observer)

java 复制代码
package DesignModel.Observer;

public interface Observer {
    
    //声明了更i性能方法
    void update(String message);
}

具体观察者(ConcrereObserver)

网站用户作为具体观察者,里面实现了更新的方法

java 复制代码
package DesignModel.Observer;

/**
 * @BelongsProject: 3.9.demo
 * @Author: yhz
 * @CreateTime: 2023-07-26  18:06
 * @Description: TODO
 * @Version: 1.0
 */
public class Blooger implements Observer{
	//博主名称
    private String bloogerName;

    public Blooger(String bloogerName) {
        this.bloogerName = bloogerName;
    }

    @Override
    public void update(String message) {
        System.out.println(bloogerName+message);
    }
}

测试:

java 复制代码
package DesignModel.Observer;

/**
 * @BelongsProject: 3.9.demo
 * @Author: yhz
 * @CreateTime: 2023-07-26  18:21
 * @Description: TODO
 * @Version: 1.0
 */
public class Test {
    public static void main(String[] args) {
        ConcreteSubject subject = new ConcreteSubject();
        Blooger blooger = new Blooger("aa1");
        Blooger blooger2 = new Blooger("aa2");
        Blooger blooger3 = new Blooger("aa3");
        Blooger blooger4 = new Blooger("aa4");

        subject.attach(blooger);
        subject.attach(blooger2);
        subject.attach(blooger3);
        subject.attach(blooger4);

        subject.notifyObservers("您关注的yhz更新了博客");
    }
}

结果打印:

java 复制代码
aa1您关注的yhz更新了博客
aa2您关注的yhz更新了博客
aa3您关注的yhz更新了博客
aa4您关注的yhz更新了博客

观察者设计模式优缺点

观察者模式的优点包括:

  • 降低了主题与观察者之间的耦合关系,两者之间是抽象耦合关系。可以很容易扩展观察者和被观察者。
  • 主题与观察者之间建立了一套触发机制。

观察者模式的缺点包括:

  • 主题与观察者之间的依赖关系并没有完全解除。
  • 当观察者对象很多时,通知的发布会花费很长时间,影响程序效率。
  • 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
  • 如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。

在使用观察者模式时,需要谨慎处理这些问题,以确保系统的稳定性和效率。

相关推荐
掘金-我是哪吒17 分钟前
分布式微服务系统架构第156集:JavaPlus技术文档平台日更-Java线程池使用指南
java·分布式·微服务·云原生·架构
亲爱的非洲野猪43 分钟前
Kafka消息积压的多维度解决方案:超越简单扩容的完整策略
java·分布式·中间件·kafka
wfsm1 小时前
spring事件使用
java·后端·spring
微风粼粼1 小时前
程序员在线接单
java·jvm·后端·python·eclipse·tomcat·dubbo
缘来是庄1 小时前
设计模式之中介者模式
java·设计模式·中介者模式
rebel2 小时前
若依框架整合 CXF 实现 WebService 改造流程(后端)
java·后端
代码的余温3 小时前
5种高效解决Maven依赖冲突的方法
java·maven
慕y2743 小时前
Java学习第十六部分——JUnit框架
java·开发语言·学习
paishishaba3 小时前
Maven
java·maven
张人玉3 小时前
C# 常量与变量
java·算法·c#