JAVA:深入了解JAVA中的23种设计模式(三)- 行为型模式(下)
一、前言
在前三篇 《深入了解JAVA中的23种设计模式(一)- 创建型模式》 《深入了解JAVA中的23种设计模式(二)- 结构型模式》 《深入了解JAVA中的23种设计模式(三)- 行为型模式(上)》 中介绍了Java中的23种设计模式的创建型模式、结构型模式与行为型模式中的一些设计模式,本文将继续讲解行为型模式剩下的设计模式。
二、行为型模式(下)
1. 备忘录模式
1.1 简介
在不破坏封装性的前提下捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后可以将对象恢复到原先保存的状态。
1.2 使用场景
需要保存和恢复数据的相关状态场景。
提供一个可回滚(rollback)的操作。
需要监控的副本场景中。
数据库连接的事务管理就是用的备忘录模式。
1.3 代码示例
/ 发起
public class Originator { private String state; public void setState(String state) { this.state = state; } public String getState() { return state; } // 创建备忘录 public Memento createMemento() { return new Memento(state); } // 使用备忘录恢复状态 public void restoreMemento(Memento memento) { this.state = memento.getState(); }
} // 备忘录
public class Memento { private String state; public Memento(String state) { this.state = state; } public String getState() { return state; }
} // 管理者
public class Caretaker { private Memento memento; public void setMemento(Memento memento) { this.memento = memento; } public Memento getMemento() { return memento; }
}
2. 状态模式
2.1 简介
允许一个对象在其内部状态改变时改变它的行为,对象看起来好像修改了它的类。其核心思想是将状态与行为绑定,不同的状态对应不同的行为。当控制一个对象状态的条件表达式过于复杂时,状态模式可以将状态的判断逻辑转移到表示不同状态的一系列类中,从而简化复杂的判断逻辑。
2.2 使用场景
当对象的行为与其当前状态密切相关,且需要在运行时根据状态改变行为时,可以使用状态模式。
当一个操作中含有庞大的多分支结构,并且这些分支取决于对象的状态时,状态模式可以简化代码并提高可维护性。
当需要避免使用大量的条件语句来控制对象的行为时,状态模式可以提供一种更加优雅的解决方案。
2.3 代码示例
/抽象状态角色
public abstract class Status {//定义一个角色,提供子类访问protected Context context;//设置角色public void setContext(Context _context){this.context = _context;}//行为1public abstract void handle1();//行为2public abstract void handle2();
}
3. 访问者模式
3.1 简介
它表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作。简单来说,访问者模式将数据操作与数据结构分离,使得在不修改数据结构的前提下,能为数据结构中的每个元素增加新的操作。
3.2 使用场景
当一个对象结构包含多个不同类型的对象,并且需要对这些对象执行不同的操作时,可以使用访问者模式。
当需要在不修改对象结构的情况下,添加新的操作或行为到对象中时,可以使用访问者模式。通过添加新的访问者类,可以实现新的操作,而无需修改现有的对象结构。
当对象结构中的对象类型相对稳定,但经常需要添加新的操作时,可以使用访问者模式。访问者模式使得添加新的操作变得简单,只需要创建新的访问者类即可。
当对象结构中的对象类型很少改变,但经常需要在这些对象上执行复杂操作时,可以使用访问者模式。访问者模式可以将复杂的操作分离出来,使得对象结构更加清晰和简单。
3.3 代码示例
// 访问者接口
interface Visitor { void visit(ElementA elementA); void visit(ElementB elementB);
} // 具体访问者类
class ConcreteVisitor implements Visitor { @Override public void visit(ElementA elementA) { System.out.println("访问 ElementA: " + elementA.getOperationA()); } @Override public void visit(ElementB elementB) { System.out.println("访问 ElementB: " + elementB.getOperationB()); }
} // 元素接口
interface Element { void accept(Visitor visitor);
} // 具体元素类 A
class ElementA implements Element { @Override public void accept(Visitor visitor) { visitor.visit(this); } public String getOperationA() { return "ElementA 的操作"; }
} // 具体元素类 B
class ElementB implements Element { @Override public void accept(Visitor visitor) { visitor.visit(this); } public String getOperationB() { return "ElementB 的操作"; }
} // 对象结构类
class ObjectStructure { private List<Element> elements = new ArrayList<>(); public void addElement(Element element) { elements.add(element); } public void accept(Visitor visitor) { for (Element element : elements) { element.accept(visitor); } }
}
4. 中介者模式
4.1 简介
该模式用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
4.2 使用场景
系统中对象之间存在复杂的引用关系,系统结构混乱且难以理解。
一个对象由于引用了其他很多对象并且直接和这些对象通信,导致难以复用该对象。想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。
4.3 代码示例
// 抽象中介者
public interface Mediator { void register(Colleague colleague); void relay(Colleague colleague, String message);
} // 具体中介者
public class ConcreteMediator implements Mediator { private List<Colleague> colleagues = new ArrayList<>(); @Override public void register(Colleague colleague) { if (!colleagues.contains(colleague)) { colleagues.add(colleague); } colleague.setMediator(this); } @Override public void relay(Colleague colleague, String message) { for (Colleague col : colleagues) { if (!col.equals(colleague)) { col.receive(message); } } }
} // 抽象同事类
public abstract class Colleague { protected Mediator mediator; public void setMediator(Mediator mediator) { this.mediator = mediator; } public abstract void receive(String message);
} // 具体同事类
public class ConcreteColleague extends Colleague { @Override public void receive(String message) { System.out.println("ConcreteColleague received message: " + message); } public void send(String message) { mediator.relay(this, message); }
}
5. 解释器模式
5.1 简介
提供了一种方式来定义语言的文法,并且建立一个解释器来解释该语言中的句子。这个模式定义了一个表示文法的类接口,以及一个解释这些文法的解释器接口。
抽象表达式(AbstractExpression):声明一个抽象的解释操作,这个接口为所有的具体表达式定义了一个统一的接口。
终结符表达式(TerminalExpression):实现了抽象表达式接口,并包含对文法中终结符的解释。
非终结符表达式(NonterminalExpression):实现了抽象表达式接口,并包含对文法中非终结符的解释。非终结符表达式通常还包含对其他表达式的引用。
环境(Context):包含解释器之外的一些全局信息,一般用来存储文法中各个终结符所对应的具体值。
客户端(Client):构建文法对应的抽象语法树,并调用解释器来解释文法。
5.2 使用场景
当有一个语言需要解释执行,并且该语言中的句子有比较简单的语法规则时,可以使用解释器模式。
当一个语言需要解释执行,并且你可将该语言中的句子表示为一个抽象语法树时,可以使用解释器模式。
当一个简单语法需要解释的场景也可以考虑使用解释器模式,如配置文件解析、数学表达式解析等。
5.3 代码示例
// 抽象表达式
interface Expression { int interpret(Context context);
} // 终结符表达式 - 数字
class NumberExpression implements Expression { private int value; public NumberExpression(int value) { this.value = value; } @Override public int interpret(Context context) { return value; }
} // 非终结符表达式 - 加法
class AdditionExpression implements Expression { private Expression left; private Expression right; public AdditionExpression(Expression left, Expression right) { this.left = left; this.right = right; } @Override public int interpret(Context context) { return left.interpret(context) + right.interpret(context); }
}
设计模式不是公式,没必要去死记硬背每一种模式,更重要的是了解它的抽象思想,以及应用设计模式怎么更好地解决问题,可以达成什么效果。理论虽多,但是我们要把它掌握的话,对于我们的实际开发来说会解决不少的问题。
相关文章:
JAVA:深入了解JAVA中的23种设计模式(三)- 行为型模式(下)
一、前言 在前三篇 《深入了解JAVA中的23种设计模式(一)- 创建型模式》 《深入了解JAVA中的23种设计模式(二)- 结构型模式》 《深入了解JAVA中的23种设计模式(三)- 行为型模式(上)》…...
微信小程序【WXML】
wxml wei xin markup language 类似于html 文档 数据绑定 小程序中使用{{}} 来进行数据绑定到模板中,如: wxml中的动态数据全部来自js中的data 简单绑定 //wxml <view> {{text }}</view>// index.js Page({data: {text: hello world}, })属性绑定…...
基于python实现的深度学习的车牌识别系统
基于python实现的深度学习的车牌识别系统 开发语言:Python 数据库:MySQL所用到的知识:Django框架工具:pycharm、Navicat、Maven 系统功能实现 登录页面 在车牌识别系统当中肯定是有登录的。怎么说呢,登录页面其实还是和最初的设…...
SQL试题使得每个学生 按照姓名的字⺟顺序依次排列 在对应的⼤洲下⾯
学⽣地理信息报告 学校有来⾃亚洲、欧洲和美洲的学⽣。 表countries 数据如下: namecontinentJaneAmericaPascalEuropeXiAsiaJackAmerica 1、编写解决⽅案实现对⼤洲(continent)列的 透视表 操作,使得每个学生 按照姓名的字⺟顺…...
kafka3.6.1版本学习
kafka目录结构 bin linux系统下可执行脚本文件 bin/windows windows系统下可执行脚本文件 config 配置文件 libs 依赖类库 licenses 许可信息 site-docs 文档 logs 服务日志 启动ZooKeeper 进入Kafka解压缩文件夹的config目录,修改zookeeper.properties配置文件 #t…...
移除链表元素-力扣
题目 给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val val 的节点,并返回 新的头节点 。 示例 1: 输入:head [1,2,6,3,4,5,6], val 6 输出:[1,2,3,4,5]示例 2: 输入&…...
HTTP请求拦截器链
文章目录 HTTP请求拦截器链需求定义写一个Controller方法接口写三个http请求拦截器把拦截器加入到配置中,并且配置拦截规则在postman里面发送请求,看下测试结果是否正确 HTTP请求拦截器链 需求定义 我们写一个包含三个HTTP请求拦截器的拦截器链&#x…...
再创佳绩丨达梦数据库一体机荣获2024数字中国创新大赛·信创赛道总决赛一等奖
5月24日,第七届数字中国建设峰会在福州盛大开幕,峰会内容安排包含开幕式、主论坛、分论坛、数字中国创新大赛、现场体验区及成果发布和专业工作会议等。武汉达梦数据库股份有限公司(以下简称达梦数据)受邀参加并在展、会、赛等多个环节深度参与。达梦全栈…...
数据分析之统计学基础
数据分析是现代企业和科研中不可或缺的一部分,而统计学是数据分析的基石。在本篇博客中,我们将介绍统计学的基础知识,涵盖数据类型、描述性统计(集中趋势、离散程度和偏差程度),并通过代码实例加以说明。 …...
Web3 游戏周报(5.19 - 5.25)
【5.19 - 5.25】Web3 游戏行业动态: Arbitrum 已开启 “2 亿枚 ARB 游戏催化剂计划”的提案投票。 STEPN 在官方 X 宣布将推出全新社交健身应用 STEPN GO。 Oasys 正式推出《足球小将》漫改 Web3 游戏《Captain Tsubasa-RIVALS-》。 Gala Games :已销…...
通过el-tree自定义渲染网页版工作目录,实现鼠标悬浮显示完整名称、用icon区分文件和文件夹等需求
目录 一、通过el-tree自定义渲染网页版工作目录 1.1、需求介绍 1.2、使用el-tree生成文档目录 1.2.1、官方基础用法 ①效果 ②代码: 1.2.2、自定义文档目录(实现鼠标悬浮显示完整名称、用icon区分文件和文件夹) ①效果(直接效…...
C语言 | Leetcode C语言题解之第101题对称二叉树
题目: 题解: /*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*/ bool isSymmetric(struct TreeNode* root) {if (root NULL) return true;//如果根为空直接…...
TTime:截图翻译/OCR
日常网页翻译Translate Web Pages完全足够,TTime最重要的功能,还是截图翻译,还有个厉害的功能,就是静默OCR,相比之前的分享的识字精灵效率更高。 软件使用 打开软件,点击翻译源设置,建议勾选一…...
【哈希】闭散列的线性探测和开散列的哈希桶解决哈希冲突(C++两种方法模拟实现哈希表)(1)
🎉博主首页: 有趣的中国人 🎉专栏首页: C进阶 🎉其它专栏: C初阶 | Linux | 初阶数据结构 小伙伴们大家好,本片文章将会讲解 哈希函数与哈希 之 闭散列的线性探测解决哈希冲突 的相关内容。 如…...
四川农业大学Java实训项目圆满收官,汇智知了堂引领学子实践创新
近日,四川农业大学与汇智知了堂共同举办的Java实训项目正式迎来了项目汇报阶段。本次实训是汇智知了堂在高等教育领域深化校企合作、推动产教融合的一次重要实践,旨在为广大学子提供一个将理论知识与实际操作相结合的平台。 在实训过程中,汇…...
JavaScript的当前时间设置及Date的运算
作者:私语茶馆 1.场景描述 如下图,在HTML刚加载时,需要将开始时间设置为默认当前时间,结束时间设置为当前时间后7天的时间。手工填写时间时,时间段不超过30天。 这里涉及到两个技术点: 1)Input Date的当前时间设置 2)date的运算 由于是动态修改HTML,所以采用…...
网络安全管理制度
一、总则 目的:本制度旨在保障组织内部网络系统的安全、稳定运行,保护组织的信息资产不受损害,确保业务的连续性和数据的完整性。适用范围:本制度适用于组织内部所有使用网络系统的部门、员工及第三方合作伙伴。 二、网络安全管理…...
零基础,想做一名网络安全工程师,该怎么学习?
相比IT类的其它岗位,网络工程师的学习方向是比较明亮的。想要成为网络工程师,华为认证就是最好的学习方法。而网络工程师的从零开始学习就是从华为认证的初级开始学起,也就是HCIA,也就是从最基本的什么是IP地址、什么是交换机这…...
【大模型部署】在C# Winform中使用文心一言ERNIE-3.5 4K 聊天模型
【大模型部署】在C# Winform中使用文心一言ERNIE-3.5 4K 聊天模型 前言 今天来写一个简单的ernie-c#的例子,主要参考了百度智能云的例子,然后自己改了改,学习了ERNIE模型的鉴权方式,数据流的格式和简单的数据解析,实…...
【Unity】Unity项目转抖音小游戏(三)资源分包,抖音云CDN
业务需求,开始接触一下抖音小游戏相关的内容,开发过程中记录一下流程。 使用资源分包可以优化游戏启动速度,是抖音小游戏推荐的一种方式,抖音云也提供存放资源的CDN服务 抖音云官方文档:https://developer.open-douyi…...
Java如何权衡是使用无序的数组还是有序的数组
在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...
在四层代理中还原真实客户端ngx_stream_realip_module
一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...
NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...
JS设计模式(4):观察者模式
JS设计模式(4):观察者模式 一、引入 在开发中,我们经常会遇到这样的场景:一个对象的状态变化需要自动通知其他对象,比如: 电商平台中,商品库存变化时需要通知所有订阅该商品的用户;新闻网站中࿰…...
华为OD机考-机房布局
import java.util.*;public class DemoTest5 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseSystem.out.println(solve(in.nextLine()));}}priv…...
区块链技术概述
区块链技术是一种去中心化、分布式账本技术,通过密码学、共识机制和智能合约等核心组件,实现数据不可篡改、透明可追溯的系统。 一、核心技术 1. 去中心化 特点:数据存储在网络中的多个节点(计算机),而非…...
JavaScript 标签加载
目录 JavaScript 标签加载script 标签的 async 和 defer 属性,分别代表什么,有什么区别1. 普通 script 标签2. async 属性3. defer 属性4. type"module"5. 各种加载方式的对比6. 使用建议 JavaScript 标签加载 script 标签的 async 和 defer …...
6.9本日总结
一、英语 复习默写list11list18,订正07年第3篇阅读 二、数学 学习线代第一讲,写15讲课后题 三、408 学习计组第二章,写计组习题 四、总结 明天结束线代第一章和计组第二章 五、明日计划 英语:复习l默写sit12list17&#…...
window 显示驱动开发-如何查询视频处理功能(三)
D3DDDICAPS_GETPROCAMPRANGE请求类型 UMD 返回指向 DXVADDI_VALUERANGE 结构的指针,该结构包含特定视频流上特定 ProcAmp 控件属性允许的值范围。 Direct3D 运行时在D3DDDIARG_GETCAPS的 pInfo 成员指向的变量中为特定视频流的 ProcAmp 控件属性指定DXVADDI_QUER…...
