设计模式 -> 观察者模式

本文详细介绍了观察者模式和发布订阅模式的概念与区别。观察者模式实现了一对多的依赖,当发布者状态改变时,所有订阅者都会收到通知并更新。发布订阅模式通过引入主题角色降低了耦合度,适用于跨应用的场景。Java中的Observable和Observer接口提供了内置的观察者模式支持。文章通过实例展示了如何在代码中实现这两种模式。
摘要由CSDN通过智能技术生成

观察者模式

观察者模式: 定义一种一对多的依赖,当一个对象状态改变的时候,所有依赖的对象都会得到通知并自动更新。

  • 也叫发布订阅模式,监听事件就是这种原理
    • 一个对象被监听着,当监听对象状态改变的时候,监听的事件就会被触发
  • 消息中间件也是这种模式,本质上也类似于监听
    • 只不过把这种监听的模式从系统里抽出来,做了个第三方工具
    • 各种优化丶调整丶增强,本质上要完成的逻辑也就是一种监听

实现

在这里插入图片描述

  • Subject类是主题(控制调节发布丶订阅两者)
    • 类似于中间人,用来监测发布者的状态通知所有订阅者执行
    • 发布着和订阅者之间解耦合,只与这个主题有关联
  • Observer类是抽象订阅者
    • 订阅者有多个,有一个接口做规范
  • ConcreteSubject类是发布者
    • 发布者执行业务逻辑的某处,调用主题中的通知方法,通知所有订阅者执行
  • ConcreteObserver是订阅者
    • 一个个订阅者,等待发布者发布消息

主题Subject

  • 首先定义一个订阅者数组,并实现增、删及通知操作。

    • 订阅者有多个,所以通知所有订阅者的前提是要保存好所有订阅者的信息
    public class Subject {
    
        //订阅者数组
        private Vector<Observer> oVector = new Vector<>();
    
        //增加一个订阅者
        public void addObserver(Observer observer) {
            this.oVector.add(observer);
        }
    
        //删除一个订阅者
        public void deleteObserver(Observer observer) {
            this.oVector.remove(observer);
        }
    
        //通知所有订阅者
        public void notifyObserver() {
            for(Observer observer : this.oVector) {
                observer.update();
            }
        }
    
    }
    

订阅者接口 -> Observer

  • 订阅者有多个,有一个接口做规范

    interface Observer {
        //更新 -> 接到通知,所有订阅者都执行这个方法
        public void update();
    }
    

发布者

  • 继承主题Subject类,为了复用主题中的通知方法

    • 如果不继承,就要手动new一个主题对象注入到发布者对象中,最后都要有所关系才行
    class ConcreteSubject extends Subject {
    
        //具体业务
        public void doSomething() {
            //...
            super.notifyObserver();//在某处执行通知
        }
    
    }
    

订阅者

  • 具体每个订阅者,在方法中执行逻辑即可

    class ConcreteObserver implements Observer {
    
        @Override
        public void update() {
            System.out.println("收到消息,进行处理");
        }
    
    }
    

main方法

  • 首先创建一个主题者

  • 然后定义一个订阅者

  • 将该订阅者添加到主题的订阅者数组中

  • 最后发布者执行逻辑,在某个时间段发布通知

    public static void main(String[] args) {
        //创建一个发布者
        ConcreteSubject subject = new ConcreteSubject();
        //定义一个订阅者
        Observer observer = new ConcreteObserver();
        //订阅者添加到主题中 -> 发布者继承了主题,所以用发布者对象就可以将订阅者添加到主题
        subject.addObserver(observer);
        //开始活动
        subject.doSomething();
    }
    
  • 其实可以看出,我们可以把主题给去掉,把所有方法都写在发布者里面

    • 这样就只剩下发布者和订阅者了,发布者对象中保存所有订阅者对象
    • 发布通知的时候,遍历所有订阅者调用方法即可
  • 这种没有主题的说法才是观察者模式

    • 观察者模式只需要一个观察者和被观察者就可以了
    • 观察者模式还是有一定的耦合性
  • 而发布订阅模式是需要抽出一个主题的,这样耦合程度就降低了

    • 而且不一定要发布者去继承主题
    • 还可以用传参的方式,将发布者和订阅者都加入到主题对象中
    • 主题只单纯的用来做通知,每进来一个发布者或者一段消息,主题就判断一下该通知哪些订阅者接受
      • 这就是消息队列了
  • 设计模式要灵活运用

  • 观察者模式,多用于单个应用内部

  • 发布订阅模式,则更多的是一种跨应用的模式(cross-application pattern),比如我们常用的消息中间件

Java有自带的观察者模式接口给我们使用

  • Observable -> 主题
public class java.util.Observable {
     private Vector<Observer> obs;

    /** 构造一个观察者为零的可观测系统. */

    public Observable() {
        obs = new Vector<>();
    }
    //添加观察者
    public synchronized void addObserver(Observer o) {
        if (o == null)
            throw new NullPointerException();
        if (!obs.contains(o)) {
            obs.addElement(o);
        }
    }
    //删除观察者
 	public synchronized void deleteObserver(Observer o) {
        obs.removeElement(o);
    }
    //通知所有观察者
    public void notifyObservers(Object arg) {
        Object[] arrLocal;
        synchronized (this) {
            if (!changed)
                return;
            arrLocal = obs.toArray();
            clearChanged();
        }

        for (int i = arrLocal.length-1; i>=0; i--)
            ((Observer)arrLocal[i]).update(this, arg);
    }
}
  • Observer -> 观察者接口
public interface java.util.Observer {
    void update(Observable o, Object arg);
}
  • 我们只要继承主题,实现我们自己的逻辑,在合适的地方调用通知
  • 实现观察者接口,加入主题中等待发布通知即可

改写我们的例子就变成

import java.util.Observable;
import java.util.Observer;

public class 观察者模式 {
    public static void main(String[] args) {
        //创建一个主题
        ConcreteSubject subject = new ConcreteSubject();
        //定义添加观察者
        subject.addObserver(new ConcreteObserver1());
        subject.addObserver(new ConcreteObserver2());
        //开始活动
        subject.doSomething();
    }
}

class ConcreteSubject extends Observable {
    //具体业务
    public void doSomething() {
        System.out.println("具体业务");
        //设置被观察者发生变化 -> 可以执行通知
        setChanged();
        //发布通知
        notifyObservers();
    }

}

class ConcreteObserver1 implements Observer {

    @Override
    public void update(Observable o, Object arg) {
        System.out.println("收到消息,进行处理1");
    }
}

class ConcreteObserver2 implements Observer {

    @Override
    public void update(Observable o, Object arg) {
        System.out.println("收到消息,进行处理2");
    }
}
具体业务
收到消息,进行处理2
收到消息,进行处理1

观察者模式就是建立一种触发机制

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值