观察者模式--java jdk中提供的支持

简介: 一、简介 观察者设计模式有如下四个角色 抽象主题角色:把所有对观察者对象的引用保存在一个集合中,每个抽象主题角色都可以有任意数量的观察者。抽象主题提供一个接口,可以增加和删除观察者角色。一般用一个抽象类或接口来实现,也可以使用非抽象类来实现。

一、简介

观察者设计模式有如下四个角色

  • 抽象主题角色:把所有对观察者对象的引用保存在一个集合中,每个抽象主题角色都可以有任意数量的观察者。抽象主题提供一个接口,可以增加和删除观察者角色。一般用一个抽象类或接口来实现,也可以使用非抽象类来实现。
  • 具体主题角色:在具体主题内部状态改变时,给所有登记过的观察者发出通知。具体主题角色通常用一个子类实现。
  • 抽象观察者角色:为所有具体的观察者定义一个接口,在得到主题的通知时更新自己。
  • 具体观察者角色:该角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。如果需要,具体观察者角色可以保存一个指向具体主题角色的引用。通常用一个子类实现。

  观察者设计模式类图如下:

二、java JDK中对观察者的支持
  java JDK中提供了Observer 与 Observable两个类。Observer类可以看作是抽象观察者角色,而Observable是抽象主题角色。

  1、Objserver 

    Objserver 是个接口,代码如下:

public interface Observer {
    /**
     * 该方法当主题对象发生改变的时候被调用. An
     * 一个应用调用主题对象的notifyObservers方法来application calls an <tt>Observable</tt> object's
     * <code>notifyObservers</code> method to have all the object's
     * observers notified of the change.
     *
     * @param   o     the observable object.
     * @param   arg   an argument passed to the <code>notifyObservers</code>
     *                 method.
     */
    void update(Observable o, Object arg);
}

  它只提供了一个update,让子类去实现。当主题对象发生改变的时候,就会调用观察者对象的update方法,从而达到观察者发生改变的目的。

  2、Observable

    Observable是个类,代码如下:

public class Observable {
    private boolean changed = false;
    private Vector 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() {
        notifyObservers(null);
    }
    
    //通知指定的观察者
    public void notifyObservers(Object arg) { 
        Object[] arrLocal;

        synchronized (this) { 
            if (!changed)//当状态没有发生改变的时候,直接返回
                return;
            arrLocal = obs.toArray();
            clearChanged();
        }
    //通知并调用观察者的update方法
        for (int i = arrLocal.length-1; i>=0; i--)
            ((Observer)arrLocal[i]).update(this, arg);
    } 
    
    //移除所有观察者
    public synchronized void deleteObservers() {
        obs.removeAllElements();
    } 

    //设置状态改变
    protected synchronized void setChanged() {
        changed = true;
    } 

    //重置状态
    protected synchronized void clearChanged() {
        changed = false;
    }

    //判断是否状态是否发生改变
    public synchronized boolean hasChanged() {
        return changed;
    }

    返回观察者的个数
    public synchronized int countObservers() {
        return obs.size();
    }
}

  从代码可以看出,我们可以让具体主题对象继承Observable类,具体观察者对象实现Observer接口并实现update方法。调用的时候只需要实例化具体主题对象与具体观察者对象,然后将具体观察者对象添加到具体主题对象中的obs(Vector)列表。当具体主题对象的状态发生该变时,调用观察者对象的update方法(这里状态发生该变指的是调用主题对象的某个方法,该方法里面有对具体观察者对象的update方法的调用)。

三、实例

  具体观察者对象

具体主题对象
package com.observer;

import java.util.Observable;
/**
 * 具体主题对象
 *
 */
public class ConcreteSubject extends Observable {

    private String info;

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }

    public void doSomething(String str) {
        System.out.println("subject: " + str);
        setInfo(str);
        setChanged();//改变主题对象的状态,这里如果不改变它的状态,则不会对观察者对象调用update方法
//        notifyObservers();//也可以不传递参数
        notifyObservers("subject is changed");//这里传递的参数是观察者对象中update方法参数列表中的第二个参数
    }
}

  具体观察者对象

package com.observer;

import java.util.Observable;
import java.util.Observer;
/**
 * 具体观察者对象
 *
 */
public class ConcreteObserver implements Observer {

    /**
     * @param subject  具体主题对象
     * @param arg notifyObservers(String str) 传递的参数
     */
    public void update(Observable o, Object arg) {
        System.out.println(arg);
        
        ConcreteSubject subject = (ConcreteSubject)o;
        System.out.println("observer: " + subject.getInfo());
    }
} 

  调用代码:

package com.observer;

import java.util.Observer;

public class Test {
    public static void main(String[] args) {
        //观察者对象
        Observer observer = new ConcreteObserver();
        Observer observer2 = new ConcreteObserver();
        Observer observer3 = new ConcreteObserver();

        //主体对象
        ConcreteSubject observable = new ConcreteSubject();
        
        //观察者加入主题对象汇总的观察者列表
        observable.addObserver(observer);
        observable.addObserver(observer2);
        observable.addObserver(observer3);

        //主体对象发生改变
        observable.doSomething("happy");
        observable.doSomething("sad");
    }
}

                                                 

目录
相关文章
|
7月前
|
设计模式 缓存 Java
Java设计模式(二):观察者模式与装饰器模式
本文深入讲解观察者模式与装饰器模式的核心概念及实现方式,涵盖从基础理论到实战应用的全面内容。观察者模式实现对象间松耦合通信,适用于事件通知机制;装饰器模式通过组合方式动态扩展对象功能,避免子类爆炸。文章通过Java示例展示两者在GUI、IO流、Web中间件等场景的应用,并提供常见陷阱与面试高频问题解析,助你写出灵活、可维护的代码。
|
5月前
|
设计模式 消息中间件 传感器
Java 设计模式之观察者模式:构建松耦合的事件响应系统
观察者模式是Java中常用的行为型设计模式,用于构建松耦合的事件响应系统。当一个对象状态改变时,所有依赖它的观察者将自动收到通知并更新。该模式通过抽象耦合实现发布-订阅机制,广泛应用于GUI事件处理、消息通知、数据监控等场景,具有良好的可扩展性和维护性。
466 8
|
7月前
|
安全 Oracle Java
JAVA高级开发必备·卓伊凡详细JDK、JRE、JVM与Java生态深度解析-形象比喻系统理解-优雅草卓伊凡
JAVA高级开发必备·卓伊凡详细JDK、JRE、JVM与Java生态深度解析-形象比喻系统理解-优雅草卓伊凡
543 0
JAVA高级开发必备·卓伊凡详细JDK、JRE、JVM与Java生态深度解析-形象比喻系统理解-优雅草卓伊凡
|
8月前
|
安全 Java 微服务
Java 最新技术和框架实操:涵盖 JDK 21 新特性与 Spring Security 6.x 安全框架搭建
本文系统整理了Java最新技术与主流框架实操内容,涵盖Java 17+新特性(如模式匹配、文本块、记录类)、Spring Boot 3微服务开发、响应式编程(WebFlux)、容器化部署(Docker+K8s)、测试与CI/CD实践,附完整代码示例和学习资源推荐,助你构建现代Java全栈开发能力。
878 1
|
8月前
|
Oracle Java 关系型数据库
新手必看:Java 开发环境搭建之 JDK 与 Maven
本文分享了 Java 学习中 JDK 安装配置与 Maven 使用的入门知识,涵盖 JDK 下载安装、环境变量设置、Maven 安装配置及本地仓库与镜像设置,帮助新手快速搭建 Java 开发环境。
980 0
|
9月前
|
安全 Java API
Java最新技术(JDK 11+) 及以上 Java 最新技术之集合框架实操应用详解
本示例基于Java最新技术(JDK 11+),涵盖集合框架的核心功能,结合Java 8+特性(如Stream API、Lambda表达式)与并发编程最佳实践。内容包括:List操作(初始化、Lambda过滤、Stream处理)、Map操作(流式过滤、ConcurrentHashMap原子操作、并行流)、Set操作(TreeSet排序、CopyOnWriteArraySet并发安全)、Queue/Deque操作(优先队列、双端队列)以及高级聚合操作(集合转换、分组统计、平均值计算)。 [代码下载](https://pan.quark.cn/s/14fcf913bae6)
181 4
|
安全 Java 编译器
JDK 10中的局部变量类型推断:Java编程的简化与革新
JDK 10引入的局部变量类型推断通过`var`关键字简化了代码编写,提高了可读性。编译器根据初始化表达式自动推断变量类型,减少了冗长的类型声明。虽然带来了诸多优点,但也有一些限制,如只能用于局部变量声明,并需立即初始化。这一特性使Java更接近动态类型语言,增强了灵活性和易用性。
297 53
|
算法 Java 编译器
深入理解 Java JDK —— 让我们从基础到进阶
JDK(Java Development Kit)是 Java 开发的核心工具包,包含编译、运行和调试 Java 程序所需的所有工具和库。它主要由 JVM(Java 虚拟机)、JRE(Java 运行时环境)和 Java 核心类库组成。JVM 是跨平台运行的基础,负责字节码的加载、执行和内存管理;JRE 提供运行 Java 应用的环境;核心类库则提供了丰富的 API 支持。通过编写、编译和运行一个简单的 Java 程序,可以深入理解 JDK 的工作原理。此外,JDK 还提供了 JIT 编译、垃圾回收优化和并发工具包等高级功能,帮助开发者提高程序性能和稳定性。
1558 10
|
Java API 数据安全/隐私保护
探索Java动态代理的奥秘:JDK vs CGLIB
动态代理是一种在 运行时动态生成代理类的技术,无需手动编写代理类代码。它通过拦截目标方法的调用,实现对核心逻辑的 无侵入式增强(如日志、事务、权限控制等)。
423 0
探索Java动态代理的奥秘:JDK vs CGLIB