安康建设网站/百度收录提交工具
前言:
为什么之前写过Golang 版的设计模式,还在重新写Java
版?
答:因为对于我而言,当然也希望对正在学习的大伙有帮助。Java作为一门纯面向对象的语言,更适合用于学习设计模式。
为什么类图要附上uml
因为很多人学习有做笔记的习惯,如果单纯的只是放一张图片,那么学习者也只能复制一张图片,可复用性较低,附上uml,方便有新理解时,快速出新图。
🔥[设计模式Java实现附plantuml源码]专链
- 创建型
- 确保对象的唯一性~单例模式
- 集中式工厂的实现~简单工厂模式
- 多态工厂的实现——工厂方法模式
- 产品族的创建——抽象工厂模式
- 对象的克隆~原型模式
- 复杂对象的组装与创建——建造者模式
- 结构型
- 提供统一入口——外观模式
- 扩展系统功能——装饰模式
- 树形结构的处理——组合模式
- 对象的间接访问——代理模式
- 不兼容结构的协调——适配器模式
- 处理多维度变化——桥接模式
- 实现对象的复用——享元模式
- 行为型
-
请求的链式处理——职责链模式
-
请求发送者与接收者解耦——命令模式
-
遍历聚合对象中的元素——迭代器模式
-
协调多个对象之间的交互——中介者模式
-
对象间的联动~观察者模式
文章目录
- 对象间的联动~观察者模式
- 简单代码实现
- 简单总结
- 主要优点
- 主要缺点
- 适用场景
对象间的联动~观察者模式
观察者模式是使用频率最高的设计模式之一,用于建立对象与对象之间的依赖关系。
一个对象发生改变时将自动通知其他对象,其他对象将相应做出反应。在观察者模式中,发生改变的对象称为观察目标,而被通知的对象称为观察者。一个观察目标可以对应多个观察者,而且这些观察者之间可以没有任何相互联系,可以根据需要增加和删除观察者,使得系统更易于扩展。
观察者模式定义如下:
观察者模式(Observer Pattern
):定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。
观察者模式的别名包括发布-订阅(Publish/Subscribe
)模式、模型-视图(Model/View
)模式、源-监听器(Source/Listener
)模式或从属者(Dependents)模式。观察者模式是一种对象行为型模式。
观察者模式结构中通常包括观察目标和观察者两个继承层次结构,其结构如图所示。
@startumlabstract class Subject {
+ attach(Observer observer)
+ detach(Observer observer)
+ notify()
}note left of Subject::notify
for(Observer obs: observers) {obs.update();
}
end noteabstract class Observer {
+ update()
}class ConcreteSubject extends Subject {
- subjectState
+ gettersetter()
}class ConcreteObserver extends Observer {
- observerState
+ update()
}note right of ConcreteObserver::update
observerState = subject.getState();
end note
Subject -right-> Observer: observers
ConcreteObserver -left-> ConcreteSubject: subject@enduml
由可以看出,在观察者模式结构图中包含以下4个角色。
(1)Subject(目标):目标又称为主题,它是指被观察的对象。在目标中定义了一个观察者集合,一个观察目标可以接受任意数量的观察者来观察,它提供一系列方法来增加和删除观察者对象,同时定义了通知方法 notify()
。目标类可以是接口,也可以是抽象类或具体类。
(2)ConcreteSubject(具体目标):具体目标是目标类的子类,通常包含有经常发生改变的数据。当它的状态发生改变时,向其各个观察者发出通知。同时它还实现了在目标类中定义的抽象业务逻辑方法(如果有)。如果无须扩展目标类,则具体目标类可以省略。
(3)Observer(观察者):观察者将对观察目标的改变做出反应。观察者一般定义为接口,该接口声明了更新数据的方法 update()
,因此又称为抽象观察者。
(4)ConcreteObserver(具体观察者):在具体观察者中维护一个指向具体目标对象的引用,它存储具体观察者的有关状态,这些状态需要和具体目标的状态保持一致。它实现了在抽象观察者Observer中声明的 update()
方法。通常在实现时,可以调用具体目标类的 attach()
方法将自己添加到目标类的集合中或通过 detach()
方法将自己从目标类的集合中删除。
观察者模式描述了如何建立对象与对象之间的依赖关系,以及如何构造满足这种需求的系统。
观察者模式包含观察目标和观察者两类对象。一个目标可以有任意数目的与之相依赖的观察者,一旦观察目标的状态发生改变,所有的观察者都将得到通知。作为对这个通知的响应,每个观察者都将监视观察目标的状态以使其状态与目标状态同步,这种交互也称为发布-订阅(Publish-Subscribe)。观察目标是通知的发布者,它发出通知时并不需要知道谁是它的观察者,可以有任意数目的观察者订阅它并接收通知。
简单代码实现
package behavior;import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;// Client code
public class ObserverDemo {public static void main(String[] args) {ConcreteSubject subject = new ConcreteSubject();new ConcreteObserverA(subject,1);ConcreteObserverB observerB = new ConcreteObserverB(subject,2);subject.setState("Initial State");subject.myNotify();subject.setState("Updated State");subject.myNotify();subject.detach(observerB);subject.setState("final State");subject.myNotify();}// 目标类public abstract static class Subject {protected HashMap<Integer, Observer> observers = new HashMap<>();public void attach(Observer observer) {observers.put(observer.id, observer);}public void detach(Observer observer) {observers.remove(observer.id);}public void myNotify() {observers.forEach((id, observer) -> observer.update() );}public abstract String getState();public abstract void setState(String state);}// Observer abstract classpublic abstract static class Observer {protected Integer id;protected String observerState;protected Subject subject;protected String prevState;// getter setterpublic abstract void update();}// ConcreteSubject classpublic static class ConcreteSubject extends Subject {private String subjectState;@Overridepublic String getState() {return subjectState;}@Overridepublic void setState(String state) {this.subjectState = state;}}// ConcreteObserver classpublic static class ConcreteObserverA extends Observer {public ConcreteObserverA(Subject subject, Integer id) {this.subject = subject;this.id = id;this.subject.attach(this);}@Overridepublic void update() {prevState = observerState;observerState = subject.getState();System.out.println(">>>>a prev state="+prevState + " new state="+observerState);}}public static class ConcreteObserverB extends Observer {public ConcreteObserverB(Subject subject, Integer id) {this.subject = subject;this.id = id;this.subject.attach(this);}@Overridepublic void update() {prevState = observerState;observerState = subject.getState();System.out.println(">>>>b prev state="+prevState + " new state="+observerState);}}
}
结果输出
>>>>a prev state=null new state=Initial State
>>>>b prev state=null new state=Initial State
>>>>a prev state=Initial State new state=Updated State
>>>>b prev state=Initial State new state=Updated State
>>>>a prev state=Updated State new state=final State
简单总结
观察者模式是一种使用频率非常高的设计模式,无论是移动应用、Web应用或者桌面应用,观察者模式几乎无处不在。它为实现对象之间的联动提供了一套完整的解决方案,凡是涉及一对一或者一对多的对象交互场景都可以使用观察者模式。观察者模式广泛应用于各种编程语言的GUI事件处理的实现,在基于事件的XML解析技术(例如SAX2)以及Web事件处理中也都使用了观察者模式。
主要优点
观察者模式的主要优点如下:
(1)观察者模式可以实现表示层和数据逻辑层的分离。它定义了稳定的消息更新传递机制,并抽象了更新接口,使得可以有各种各样不同的表示层充当具体观察者角色。
(2)观察者模式在观察目标和观察者之间建立一个抽象的耦合。观察目标只需要维持一个抽象观察者的集合,无须了解其具体观察者。由于观察目标和观察者没有紧密地耦合在一起,因此它们可以属于不同的抽象化层次。
(3)观察者模式支持广播通信。观察目标会向所有已注册的观察者对象发送通知,简化了一对多系统设计的难度。
(4)观察者模式满足开闭原则的要求,增加新的具体观察者无须修改原有系统代码。在具体观察者与观察目标之间不存在关联关系的情况下,增加新的观察目标也很方便。
主要缺点
观察者模式的主要缺点如下:
(1)如果一个观察目标对象有很多直接和间接观察者,将所有的观察者都通知到会花费很多时间。
(2)如果在观察者和观察目标之间存在循环依赖,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
(3)观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
适用场景
在以下情况下可以考虑使用观察者模式:
(1)一个抽象模型有两个方面,其中一个方面依赖于另一个方面,将这两个方面封装在独立的对象中使它们可以各自独立地改变和复用。
(2)一个对象的改变将导致一个或多个其他对象也发生改变,而并不知道具体有多少对象将发生改变,也不知道这些对象是谁。
(3)需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……可以使用观察者模式创建一种链式触发机制。
🚀 作者简介:作为某云服务提供商的后端开发人员,我将在这里与大家简要分享一些实用的开发小技巧。在我的职业生涯中积累了丰富的经验,希望能通过这个博客与大家交流、学习和成长。技术栈:Java、Golang、PHP、Python、Vue、React
本文收录于三木的
💐 「设计模式」专栏
此外三木还有以下专栏在同步更新~
🌼 「AI」专栏
🔥「面试」这个专栏的灵感来自于许多粉丝私信,大家向我咨询有关面试的问题和建议。我深感荣幸和责任,希望通过这个专栏,能够为大家提供更多关于面试的知识、技巧和经验。我们将一起探讨面试。期待粉丝们ssp的offer喜讯。
🎈 「Java探索者之路」系列专栏,这个专栏旨在引领Java开发者踏上一段真正探索Java世界的旅程。
我们将深入探讨Java编程的方方面面,从基础知识到高级技巧,从实践案例到最新趋势,帮助你成为一名卓越的Java探索者。如果有想进入Java后端领域工作的同学,这个专栏会对你有所帮助,欢迎关注起来呀
🌊 「Python爬虫」的入门学习系列,大家有兴趣的可以看一看
🌹一起学习,互三互访,顺评论区有访必回,有关必回!!!
相关文章:

[设计模式Java实现附plantuml源码~行为型]对象间的联动~观察者模式
前言: 为什么之前写过Golang 版的设计模式,还在重新写Java 版? 答:因为对于我而言,当然也希望对正在学习的大伙有帮助。Java作为一门纯面向对象的语言,更适合用于学习设计模式。 为什么类图要附上uml 因为很…...

vue3+js 实现记住密码功能
常见的几种实现方式 1 基于spring security 的remember me 功能 localStorage 除非主动清除localStorage 里的信息 ,不然永远存在,关闭浏览器之后下次启动仍然存在 存放数据大小一般为5M 不与服务器进行交互通信 cookies 可以…...

基于单片机的太阳能电池板自动跟踪系统的研究
摘要 伴随着人类社会的发展,人口基数越来越大,电量消耗巨大,传统发电原 料污染环境的同时,可用量日益减少,给人类未来生产生活带来了一定的威胁, 因而解决日益剧增的用电量,寻求一种新能源显得极其重要。论文正是基于此 背景下,针对当前太阳能电池板采光率低、自动化水…...

React 模态框的设计(二)
自定义组件是每个前端开发者必备的技能。我们在使用现有框架时难免有一些超乎框架以处的特别的需求,比如关于弹窗,每个应用都会用到,但是有时我们使用的框架中提供的弹窗功能也是功能有限,无法满足我们的应用需求,今天…...

操作符详解3
✨✨ 欢迎大家来到莉莉的博文✨✨ 🎈🎈养成好习惯,先赞后看哦~🎈🎈 前面我们已经讲过算术操作符、赋值操作符、逻辑操作符、条件操作符和部分的单目操作 符,今天继续介绍一部分。 目录 1.操作符的分类 2…...

【C语言基础】:操作符详解(一)
文章目录 操作符详解1. 操作符的分类2. 二进制和进制转换2.1 什么是二进制、八进制、十进制、十六进制2.1.1 二进制和进制转换2.1.2 二进制转十进制2.2.3 二进制转八进制2.2.4 二进制转十六进制 3. 源码、反码、补码4. 移位操作符4.1 左移操作符4.2 右移操作符 5. 位操作符&…...

通俗易懂分析:Vite和Webpack的区别
1、对项目构建的理解 先从浏览器出发, 浏览器是由浏览器内核和JS引擎组成;浏览器内核编译解析html代码和css代码,js引擎编译解析JavaScript代码;所以从本质上,浏览器只能识别运行JavaScript、CSS、HTML代码。 而我们在…...

OpenCart程序结构与业务逻辑
一、程序业务逻辑说明 在 OpenCart 中,index.php 文件是整个应用程序的入口文件,它负责初始化应用程序并调度请求。以下是 index.php 文件加载执行的流程: 1. **设置路径常量:** - index.php 首先定义了一些重要的路径常量&…...

软件License授权原理
软件License授权原理 你知道License是如何防止别人破解的吗?本文将介绍License的生成原理,理解了License的授权原理你不但可以防止别人破解你的License,你甚至可以研究别人的License找到它们的漏洞。喜欢本文的朋友建议收藏+关注,方便以后复习查阅。 什么是License? 在…...

C/C++实现老鼠走迷宫
老鼠形象可以辨认,可以用上下左右操纵老鼠;正确检测结果,若老鼠在规定的时间内走到粮仓,提示成功,否则提示失败。代码分为3个文件:main.cpp、play.h、play.cpp。 main.cpp: #include <iostream> #include <…...

[Linux]文件基础-如何管理文件
回顾C语言之 - 文件如何被写入 fopen fwrite fread fclose fseek … 这一系列函数都是C语言中对文件进行的操作: int main() {FILE* fpfopen("text","w");char str[20]"write into text";fputs(str,fp);fclose(fp);return 0; }而上…...

bat 查找文件所在
脚本 在批处理文件(.bat)中查找文件所在的目录,你可以使用dir命令结合循环和条件语句来实现。以下是一个简单的示例,演示如何在批处理文件中查找指定文件并输出其所在目录: echo off setlocal enabledelayedexpansio…...

程序员的守护神:为何电脑永不熄灭?
在这个信息时代,程序员成了推动社会进步的“隐形英雄”。他们通宵达旦,手指在键盘上跳跃,创造出一个个令人惊叹的数字世界。有趣的是,你可能注意到了一个现象:程序员似乎总是不关电脑。这并非他们对电脑上瘾࿰…...

Kafka快速实战以及基本原理详解
Kafka快速实战以及基本原理详解 基本概念 Kafka是一个分布式、支持分区、多副本,基于ZK的分布式消息系统,最大的特性就是可以实时的处理大量数据以满足各种需求场景,比如Hadoop的批处理系统、低延迟的实时系统、Storm/Spark流式处理引擎、日…...

微信小程序(4)- 事件系统和模板语法
1. 事件系统 1.1 事件绑定和事件对象 小程序中绑定事件与在网页开发中绑定事件几乎一致,只不过在小程序不能通过 on 的方式绑定事件,也没有 click 等事件,小程序中绑定事件使用 bind 方法,click 事件也需要使用 tap 事件来进行代…...

【Java多线程】对线程池的理解并模拟实现线程池
目录 1、池 1.1、线程池 2、ThreadPoolExecutor 线程池类 3、Executors 工厂类 4、模拟实现线程池 1、池 “池”这个概念见到非常多,例如常量池、数据库连接池、线程池、进程池、内存池。 所谓“池”的概念就是:(提高效率) 1…...

python连接mysql数据库
连接MySQL数据库,通常我们会使用Python的mysql-connector-python库。下面是一个基本的示例来展示如何使用Python连接到MySQL数据库。 首先,确保你已经安装了mysql-connector-python库。如果没有,你可以使用pip来安装它: pip ins…...

docker用法
首先需要去docker官网注册你的账号,记住账号名称和密码; 然后在本地执行: docker login登录OK。 把ubuntu下载到本地: sudo docker pull ubuntusudo docker images输出: REPOSITORY TAG …...

DIcom调试Planar configuration
最近和CBCT组同事调dicom图像 这边得图像模块老不兼容对方得dicom文件。 vtk兼容,自己写得原生解析不兼容。 给对方调好了格式,下次生成文件还会有错。 简单记录下,日后备查。 今天对方又加了 个字段:Planar configuration 查…...

C#与VisionPro联合开发——跳转页面
1、跳转页面并打开相机 From1 所有代码展示 using System; using System.IO; using System.Windows.Forms; //引入VisionPro命名空间 using Cognex.VisionPro;namespace ConnectCamera {public partial class Form1 : Form {public Form1() {InitializeComponent();}CogAcqFif…...

服务端测试开发必备技能:Mock测试
什么是mock测试 Mock 测试就是在测试活动中,对于某些不容易构造或者不容易获取的数据/场景,用一个Mock对象来创建以便测试的测试方法。 Mock测试常见场景 无法控制第三方系统接口的返回,返回的数据不满足要求依赖的接口还未开发完成&#…...

vue3中ref创建变量取值时自动补充 .value 插件 volar
插件 TypeScript Vue Plugin (Volar) 设置中配置...

clickhouse的docker部署与springboot整合
注意:镜像bitnami/clickhouse包含服务端和客户端,yandex版本需要使用yandex/clickhouse-server,yandex/clickhouse-server docker启动命令(允许空密码 -e ALLOW_EMPTY_PASSWORD=yes),clickhouse版本不同,配置文件在的位置也会不一样/etc/clickhouse-server/config.xml d…...

Node.js_基础知识(计算机硬件基础)
主机的基本组成 CPU:Central Processing Unit,即中央处理器,是计算机的核心部件。是一块集成电路芯片,能够执行计算机指令并控制计算机的各种操作,负责运算和处理数据内存:是电脑硬件中的一块电路板,用于暂时存储CPU中的运算数据,是计算机与CPU进行沟通的桥梁,负责存储…...

git bash :download.sh: line 1: wget: command not found(已解决)
Windows中git bash完全可以替代原生的cmd,但是对于git bash会有一些Linux下广泛使用的命令的缺失,比如wget命令。 1、下载wget.exe,地址:https://eternallybored.org/misc/wget/ 2、将wget.exe 拷贝到C:\Program Files\Git\ming…...

BlackberryQ10 是可以安装 Android 4.3 应用的,Web UserAgent 版本信息
BlackberryQ10 是可以安装 Android 4.3 应用的 最近淘了个 Q10 手机,非常稀罕它,拿着手感一流。这么好的东西,就想给它装点东西,但目前所有的应用都已经抛弃这个安卓版本了。 一、开发环境介绍 BlackBerry Q10 的 安卓版本是 4.…...

JS前端高频面试
JS数据类型有哪些,区别是什么 js数据类型分为原始数据类型和引用数据类型。 原始数据类型包括:number,string,boolean,null,undefined,和es6新增的两种类型:bigint 和 symbol。&am…...

Flask数据库操作-Flask-SQLAlchemy
Flask中一般使用flask-sqlalchemy来操作数据库。flask-sqlalchemy的使用介绍如下: 一、SQLAlchemy SQLALchemy 实际上是对数据库的抽象,让开发者不用直接和 SQL 语句打交道,而是通过 Python 对象来操作数据库,在舍弃一些性能开销…...

H5获取手机相机或相册图片两种方式-Android通过webview传递多张照片给H5
需求目的: 手机机通过webView展示H5网页,在特殊场景下,需要使用相机拍照或者从相册获取照片,上传后台。 完整流程效果: 如下图 一、H5界面样例代码 使用html文件格式,文件直接打开就可以展示布局&#…...

mysql进阶学习 | DAY 14
存储引擎 体系结构 连接层 服务层 引擎层 存储层 存储引擎 表类型 查看引擎 查看建表语句 指定存储引擎 ENGINE SHOW engins InnoDB 默认存储引擎 遵循ACID模型 支持事务 行级锁 提高并发访问性能 支持外键 FOREIGN KEY约束 保证数据完整性和正确性 对应文件 xx…...