观察者模式——解决解耦的钥匙

● 观察者模式介绍

观察者模式是一个使用频率非常高的模式,它最常用的地方是GUI系统、订阅------发布系统。因为这个模式的一个重要作用就是解耦,将被观察者和观察者解耦,使得它们之间依赖性更小,甚至做到毫无依赖。以CUI系统来说,应用的UI具有易变性,尤其是前期随着业务的改变或者产品的需要修改,应用界面也会经常性变化,但是业务逻辑基本变化不大,此时,GUI系统需要一套机制来应对这种情况,使得UI层与具体的业务逻辑解耦,观察者模式此时就派上用场了。

● 观察者模式的定义

定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖它的对象都会得到通知并被自动更新。

● 观察者模式的使用场景

关联行为场景,需要注意的是,关联行为是可拆分的,而不是"组合"关系;

事件对接触发场景;

跨系统的消息交换场景,如消息队列、事件总线的处理机制。

● 观察者模式的UML类图

UML类图下图所示。

角色介绍。

Subject:抽象主题,也就是被观察者(Observable)的角色,抽象主题角色把所有观察者对象的引用在一个集合里,每个主题都可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象。

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

Observer:抽象观察者,该角色是观察者的抽象类,它定义了一个更新接口,使得在得到主题的更改通知时更新自己。

ConcreteObserver:具体的观察者,该角色实现抽象观察者角色所定义的更新接口,以便在主题的状态发生变化时更新自身状态。

● 观察者模式的简单实现

假设有一个开发技术前线网站,是一个聚合了关于Android、iOS新技术文章的开源库等内容的网站,在这里可以看到新技术、强大的开源库、新的信息,经常浏览这两网站不仅能够开阔眼界,也能让我们接触到前沿的科技信息。

开发技术前线不仅是个内容发布页面,也支持用户邮箱订阅,每周发布周报后会将优质的内容推送给订阅用户,这种模式叫做发布------订阅模式,它的另一个名称是观察者模式。

下面让我们来简单模拟一下开发技术前线的发布------订阅过程。

java 复制代码
/**
 * 程序是观察者
 */
public class Coder implements Observer {
    public String name;

    public Coder(String name) {
        this.name = name;
    }

    @Override
    public void update(Observable o, Object arg) {
        System.out.println("Hi, " + name + ", DevTechFrontier更新新, 内容:" + arg);

    }

    @NonNull
    @Override
    public String toString() {
        return "码农:" + name;
    }
}
java 复制代码
/**
 * DevTechFrontier 即开发技术前线,这个网站是被观察者角色,当它有更新时所有的观察者(这里是程序员)
 * 都接到相应的通知
 */
public class DevTechFrontier extends Observable {

    public void postNewPublication(String content) {
        //标识状态或者内容发生改变
        setChanged();
        //通知所有观察者
        notifyObservers(content);
    }
}
java 复制代码
/**
 * 测试代码
 */
public class Test {
    public static void main(String[] args) {
        //被观察的角色
        DevTechFrontier devTechFrontier = new DevTechFrontier();
        Coder mrsimple = new Coder("mr.simple");
        Coder coder1 = new Coder("coder-1");
        Coder coder2 = new Coder("coder-2");
        Coder coder3 = new Coder("coder-3");

        //将观察者注册到可观察对象的观察者列表中
        devTechFrontier.addObserver(mrsimple);
        devTechFrontier.addObserver(coder1);
        devTechFrontier.addObserver(coder2);
        devTechFrontier.addObserver(coder3);

        //发布消息
        devTechFrontier.postNewPublication("新的一期开发技术前线周报发布啦!");
    }
}

输出结果:

可以看到所有订阅了开发技术前线的用户都收到了更新消息,一对多的订阅------发布系统就完成了。

Oblerver和Observable是JDK中内置类型,可见观察者模式是非常重要的,这里Obsserver是抽象的观察者角色,Coder扮演的是具体观察者的角色:Observable对应的是抽象主题角色,DevTechFrontier则是具体的主题角色。Coder是具体的观察者,它们订阅了DevTechFrontier这个具体的可观察对象,当DevTechFrontier有更新时,会遍历所有观察者(这里是Coder),然后给这些观察者发布一个更新的消息,即调用Observer和Observable这些抽象类,因此,Coder和DevTechFrontier完全没有耦合,保证了订阅系统的灵活性、可扩展性。

相关推荐
什巳2 小时前
JAVA练习275-乘积最大子数组
java·开发语言·数据结构·算法
lang201509282 小时前
Apache POI Word(docx) 实战教程:从入门到精通表格合并、图片插入与文档合并
java·开发语言·word
小牛不牛的程序员2 小时前
利用Claude Code构建自动化需求挖掘工具:从原理到实践
java·算法·自动化
Robot_Nav2 小时前
C++ 面试常问问题汇总:基础语法、面向对象、STL、多线程与设计模式
c++·设计模式·面试
wear工程师2 小时前
腾讯天美一面:从 HashMap 到 Spring 事务,面试官这套连环问到底在考什么
java·面试
浩瀚地学3 小时前
【Java基础复习】IO流(二)
java·开发语言·经验分享·笔记·学习
hdsoft_huge3 小时前
SpringBoot系列06:RESTful接口开发,请求参数接收、全局跨域CORS完整配置
java·spring boot
IVVi0jToe3 小时前
高效C++线程池设计与实现
java·c++·安全
QiLinkOS3 小时前
QiLink OS的失败数据共享平台的运作模式是否适用于所有行业?
android·开发语言·人工智能·算法·重构·开源
CRMEB定制开发3 小时前
企业级Java电商系统选型路线图:从零到上线全流程拆解
java·开发语言·商城系统·小程序商城