设计模式-第11章(观察者模式)

news2025/7/29 6:33:07

观察者模式

  • 观察者模式
  • 观察者模式的特点
  • 老板回来了

观察者模式

观察者模式又叫发布订阅模式。

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

在这里插入图片描述
Subject类,抽象的通知者,一般用一个接口或抽象类实现。它把所有的观察者对象的引用都保存起来,每个通知者可以有任意数量的观察者。抽象通知者通过了接口,可以增加和删除观察者对象。

Observer类,抽象观察者,为所有的具体观察者定义一个接口,在得到通知者的通知时更新自己。

ConcreteSubject 类,具体的通知者,内部引用了观察者,在特定情况下可以通知所有的观察者,更新观察者的状态。

ConcreteSubject 类,具体的观察者,实现抽象观察者角色所要求的更新接口,以便根据通知者的状态更新自己的状态。观察者可保存一个指向具体通知者对象的引用。

基本代码结构

通知者抽象类

abstract class Subject{
    private ArrayList<Observer> list = new ArrayList<Observer>();//针对抽象的Observer编程
    //增加观察者
    public void attach(Observer observer){
        list.add(observer);
    }
    //减少观察者
    public void detach(Observer observer){
        list.remove(observer);
    }
    //通知观察者
    public void notifyObserver(){
        for(Observer item : list){
            item.update();
        }
    }
    // 通知者的状态
    protected String subjectState;
    public String getSubjectState(){
        return this.subjectState;
    }
    public void setSubjectState(String value){
        this.subjectState = value;
    }
}

具体通知者

class ConcreteSubject extends Subject{
    //具体通知者的方法
}

抽象观察者

abstract class Observer{
	// 定义了一个抽象更新方法,根据通知者,更新自身的状态
    public abstract void update();
}

具体观察者类

class ConcreteObserver extends Observer{
    private String name;
    // 引用通知者,根据通知者的状态,进行更新
    private Subject sub;
    public ConcreteObserver(String name,Subject sub){
        this.name = name;
        this.sub = sub;
    }
    public void update(){
    	// 实现更新方法	
        System.out.println("观察者"+this.name+"的新状态是"+this.sub.getSubjectState());
    }
}

客户端

public class Test {
	public static void main(String[] args){
		System.out.println("**********************************************");		
		System.out.println("《大话设计模式》代码样例");
		System.out.println();		
        Subject subject = new ConcreteSubject();
        subject.attach(new ConcreteObserver("NameX",subject));
        subject.attach(new ConcreteObserver("NameY",subject));
        subject.attach(new ConcreteObserver("NameZ",subject));
        subject.setSubjectState("ABC");
        subject.notifyObserver();
		System.out.println();
		System.out.println("**********************************************");
	}
}

观察者模式的特点

将一个系统分割成一系列相互协作的类有一个不好的副作用,就是需要维护相关对象的一致性。不能为了维护一致性而使各类紧密耦合,这样会给维护,扩展和重用带来不便。
在观察者模式中,通知者和观察者进行了解耦。一个通知者可以被任意多个观察者依赖,一旦通知者的状态发生改变,就会通知所有观察者。而通知者发出通知的时候,并不需要具体的观察者是谁,依赖相同的通知者的观察者之间也是透明的。

什么时候使用观察者模式?

  • 当一个对象改变需要同时改变其他对象的时候,而这个对象并不知道具体有多少个对象有待改变,应该考虑使用观察者模式。
  • 当一个抽象模型有两个方面,其中一个方面依赖于另一个方面,这时用观察者模式可以将这两者封装在独立的对象使它们各自独立的改变和复用。

观察者模式所做的工作其实就是在解除耦合。让耦合的双方都依赖于抽象,而不是依赖于具体。从而使得各自的变化都不会影响另一边的变化。

老板回来了

老板不在,员工摸鱼,老板回来,通知员工工作。

在Java中,已经为观察者模式准备好了相关的接口和抽象类了。
观察者接口 java.util.Observer 和 通知者类 java.util.Observable
在这里插入图片描述
具体观察者(炒股的员工)

class StockObserver implements Observer{
    protected String name;
    public StockObserver(String name){
        this.name = name;
    }
    public void update(Observable o, Object arg){ 
        Subject b = (Subject)o;
        System.out.println(b.name+":"+b.getAction()+"!"+this.name+",请关闭股票行情,赶紧工作。");
    }
}

具体的观察者(看NBA员工)

class NBAObserver implements Observer{
    protected String name;
    public NBAObserver(String name){
        this.name = name;
    }
    public void update(Observable o, Object arg){
        Subject b = (Subject)o;
        System.out.println(b.name+":"+b.getAction()+"!"+this.name+",请关闭NBA直播,赶紧工作。");
    }
}

通知者类,继承扩展已有的类

class Subject extends Observable{
    protected String name;
    private String action;
    public Subject(String name){
        this.name = name;
    }
    //得到状态
    public String getAction(){
        return this.action;
    }
    //设置状态(就是设置具体通知的话)
    public void setAction(String value){
        this.action = value;
        // 改变状态
        setChanged();
        // 通知所有观察者
        notifyObservers();
    }
}

具体的通知者(老板)

class Boss extends Subject{
    public Boss(String name){
        super(name);
    }
}

客户端

public class Test {
    public static void main(String[] args){
        System.out.println("**********************************************");       
        System.out.println("《大话设计模式》代码样例");
        System.out.println();       
        //老板胡汉三
        Boss boss1 = new Boss("胡汉三");
        //看股票的同事
        Observer employee1 = new StockObserver("魏关姹");
        Observer employee2 = new StockObserver("易管查");
        Observer employee3 = new NBAObserver("兰秋幂");
        //老板登记下三个同事
        boss1.addObserver(employee1);
        boss1.addObserver(employee2);
        boss1.addObserver(employee3);
        boss1.deleteObserver(employee1); //魏关姹其实没有被通知到,所有减去
        //老板回来
        boss1.setAction("我胡汉三回来了");        
        System.out.println();
        System.out.println("**********************************************");
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/394620.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

nextcloud挂载阿里云oss 过程

1. 情景 &#xff1a; 已经使用docke-compsoe 搭建起来nextcloud 并投入使用 &#xff0c;现在内存不够需要挂一个oss nextcloud挂载阿里云oss大概思路 &#xff1a; 使用阿里官方提供的 ossfs &#xff0c; 将oss挂载到服务器目录中 &#xff0c; 在docker-compose中的 做容…

ArcGIS10.6“License许可启动无响应”解决方法

以下是我尝试过的方法关闭防火墙&#xff08;很必要&#xff09;替换 “Service.txt” 及 "ARCGIS.exe"文件&#xff08;感觉没什么用&#xff09;修改服务设置&#xff08;很必要&#xff09;更改注册表&#xff08;可有&#xff09;更改端口号&#xff08;好像没什…

My RuoYi 微服务

一 快速了解 文档&#xff08;特别详细&#xff09;&#xff1a;介绍 | RuoYi 介绍 技术架构&#xff08;图&#xff09;&#xff1a;介绍 | RuoYi快速了解 技术选型 系统环境主框架持久层视图层内置功能 用户管理&#xff1a;用户是系统操作者&#xff0c;该功能主要完成系…

HBase---HBase基础语法

HBase基础语法 文章目录HBase基础语法基本操作进入 HBase 客户端命令行查看命名空间查看命名空间下的表创建命名空间创建表查看表描述禁用/启用删除表新增列族删除列族更改列族存储版本的限制put 增加数据get 查看数据get条件查询删除指定列族下的指定列删除指定行全表扫描全表…

Java线程池之线程复用原理解析

什么是线程复用 在Java中&#xff0c;我们正常创建线程执行任务&#xff0c;一般都是一条线程绑定一个Runnable执行任务。而Runnable实际只是一个普通接口&#xff0c;真正要执行&#xff0c;则还是利用了Thread类的run方法。这个rurn方法由native本地方法start0进行调用。我们…

2023最新设计模式常见面试题汇总进大厂必备

2023最新设计模式常见面试题汇总1.说一下设计模式&#xff1f;你都知道哪些&#xff1f;2.什么是单例模式&#xff1f;3.什么是简单工厂模式&#xff1f;4.什么是抽象工厂模式&#xff1f;5.什么是观察者模式&#xff1f;1&#xff09;定义观察者&#xff08;消息接收方&#x…

201809-3 CCF 元素选择器 满分题解(超详细注释代码) + 解题思路(超详细)

问题描述 解题思路 根据题意可以知道在查询中可以分为两种情况 第一种是查询一个标签选择器或者id选择器&#xff08;可以称为一级查询&#xff09; 第二种就是存在大于两级的查询&#xff08;可以称为多级查询&#xff09; 显然第一种查询需要存储每一种元素在内容中所有出现…

2023 最新计算机视觉学习路线(入门篇)

计算机视觉是人工智能的一个领域&#xff0c;专注于教计算机解释和理解视觉世界。它涉及使用算法、深度学习模型和其他技术使机器能够识别图像或视频中的对象。计算机视觉可用于各种任务&#xff0c;如面部识别、目标检测、图像分割、运动估计和跟踪等。重要性计算机视觉的重要…

Leetcode DAY 57: 回文子串 and 最长回文子序列

647. 回文子串 题目&#xff1a; Given a string s, return the number of palindromic substrings in it. A string is a palindrome when it reads the same backward as forward. A substring is a contiguous sequence of characters within the string. 1、暴力解法&#…

docker-compose+HAProxy+Keepalived搭建高可用 RabbitMQ 集群

基础环境准备 系统环境&#xff1a;Centos7.6 Docker version&#xff1a; 1.13.1, build 7d71120/1.13.1 Docker Compose version&#xff1a; v2.2.2 三个节点&#xff1a; 10.10.11.79 &#xff08;这一台做rabbitmq集群根节点&#xff09; 10.10.11.80 (这台做haproxyke…

K8S Pod健康检查

因为 k8s 中采用大量的异步机制、以及多种对象关系设计上的解耦&#xff0c;当应用实例数 增加/删除、或者应用版本发生变化触发滚动升级时&#xff0c;系统并不能保证应用相关的 service、ingress 配置总是及时能完成刷新。在一些情况下&#xff0c;往往只是新的 Pod 完成自身…

Python|蓝桥杯进阶第二卷——贪心

欢迎交流学习~~ 专栏&#xff1a; 蓝桥杯Python组刷题日寄 蓝桥杯进阶系列&#xff1a; &#x1f3c6; Python | 蓝桥杯进阶第一卷——字符串 &#x1f50e; Python | 蓝桥杯进阶第二卷——贪心 &#x1f49d; Python | 蓝桥杯进阶第三卷——动态规划&#xff08;待续&#xf…

关于信息安全认证CISP、PTE对比分析

CISP 注册信息安全专业人员 CISP-PTE 注册渗透测试工程师&#xff08;以下简称PTE&#xff09; 1 、发证机构 CISP与PTE的发证机构都是中国信息安全测评中心&#xff0c;政府背景给认证做背书&#xff0c;学员信息都在中国政府可控的机构手中&#xff1b; 如果想在政府、国…

TryHackMe-Tardigrade(应急响应)

Tardigrade 您能否在此 Linux 端点中找到所有基本的持久性机制&#xff1f; 服务器已遭到入侵&#xff0c;安全团队已决定隔离计算机&#xff0c;直到对其进行彻底清理。事件响应团队的初步检查显示&#xff0c;有五个不同的后门。你的工作是在发出信号以使服务器恢复生产之前…

MyBatis源码分析(七)MyBatis与Spring的整合原理与源码分析

文章目录写在前面一、SqlSessionFactoryBean配置SqlSessionFactory1、初识SqlSessionFactoryBean2、实现ApplicationListener3、实现InitializingBean接口4、实现FactoryBean接口5、构建SqlSessionFactory二、SqlSessionTemplate1、初始SqlSessionTemplate2、SqlSessionTemplat…

这个WPF DataGrid组件,可以让业务数据管理更轻松!(Part 2)

DevExpress WPF的DataGrid组件是专用于WPF平台的高性能XAML网格控件&#xff0c;该组件附带了几十个具有高影响力的功能&#xff0c;使开发者可以轻松地管理数据并根据也无需要在屏幕上显示数据。在上文中&#xff08;点击这里回顾>>&#xff09;为大家介绍了DevExpress …

HTTPS详解(原理、中间人攻击、CA流程)

摘要我们访问浏览器也经常可以看到https开头的网址&#xff0c;那么什么是https&#xff0c;什么是ca证书&#xff0c;认证流程怎样&#xff1f;这里一一介绍。原理https就是httpssl&#xff0c;即用http协议传输数据&#xff0c;数据用ssl/tls协议加密解密。具体流程如下图&am…

企业级信息系统开发学习笔记1.8 基于Java配置方式使用Spring MVC

文章目录零、本节学习目标一、基于Java配置与注解的方式使用Spring MVC1、创建Maven项目 - SpringMVCDemo20202、在pom.xml文件里添加相关依赖3、创建日志属性文件 - log4j.properties4、创建首页文件 - index.jsp5、创建Spring MVC配置类 - SpringMvcConfig6、创建Web应用初始…

C++基础了解-02-C++ 数据类型

C 数据类型 一、C 数据类型 使用编程语言进行编程时&#xff0c;需要用到各种变量来存储各种信息。变量保留的是它所存储的值的内存位置。这意味着&#xff0c;当创建一个变量时&#xff0c;就会在内存中保留一些空间。 可能需要存储各种数据类型&#xff08;比如字符型、宽…

JDK如何判断自己是什么公司的

0x00 前言 因为一些事情&#xff0c;遇到了这样一个问题&#xff0c;JDK如何判断自己是什么公司编译的。因为不同的公司编译出来&#xff0c;涉及到是否商用收费的问题。 平时自己使用的时候&#xff0c;是不会考虑到JDK的编译公司是哪一个&#xff0c;都是直接拿起来用&#…