浅谈Java23种设计模式之11种行为型模式的使用场景(第一部分)

前言:
这是设计模式的第三期;继续根据实际开发应用场景解析这11种行为型设计模式,也是在实际开发中经常会用到的,希望给同学们带来帮助.
为了减少阅读疲劳 我会分成三部分详细诠释.

1.责任链模式(Chain of Responsibility)

概念:

它允许你将请求沿着处理者链进行传递,直到找到合适的处理者来处理该请求。每个处理者都可以决定是否处理请求,如果不能处理,则将请求传递给链中的下一个处理者。这种模式可以用来实现请求的多级处理,以及解耦请求发送者和接收者。

实际使用场景:

假设我们正在开发一个简单的日志记录系统,系统需要根据日志级别(DEBUG, INFO, WARNING, ERROR)来决定如何处理日志信息。我们可以使用责任链模式,让不同级别的处理器依次尝试处理日志,直到找到合适的处理器为止。

直接上代码:

a.抽象处理者

public interface Logger {void log(int level, String message);void setNextLogger(Logger nextLogger);
}

b.具体处理者

public class DebugLogger implements Logger {private Logger nextLogger;@Overridepublic void log(int level, String message) {if (level == LogLevel.DEBUG) {System.out.println("DEBUG: " + message);} else if (nextLogger != null) {nextLogger.log(level, message);}}@Overridepublic void setNextLogger(Logger nextLogger) {this.nextLogger = nextLogger;}
}

c.客户端代码

public class ChainOfResponsibilityDemo {public static void main(String[] args) {// 构建责任链Logger debugLogger = new DebugLogger();Logger infoLogger = new InfoLogger();Logger warningLogger = new WarningLogger();Logger errorLogger = new ErrorLogger();debugLogger.setNextLogger(infoLogger);infoLogger.setNextLogger(warningLogger);warningLogger.setNextLogger(errorLogger);// 发出日志请求debugLogger.log(LogLevel.DEBUG, "Debugging information.");infoLogger.log(LogLevel.INFO, "Informational message.");warningLogger.log(LogLevel.WARNING, "Warning occurred!");errorLogger.log(LogLevel.ERROR, "An error has happened!");}
}
// 假设的日志级别枚举简化表示
enum LogLevel {DEBUG, INFO, WARNING, ERROR
}

说明
在这个例子中,每个日志处理器类(如DebugLogger)都实现了log方法,该方法首先判断当前日志级别是否匹配,如果匹配则处理日志,否则将请求转发给链中的下一个处理器。通过链式调用,请求会一直传递直到被处理或到达链的末端。

责任链模式的优势在于它提供了一种避免请求发送者与接收者耦合的方式,使得系统更易于扩展和维护。如果需要添加新的日志处理逻辑,只需添加一个新的处理者类并插入到链中即可,无需修改现有的处理者或客户端代码。

2.命令模式(Command)

概念:

它将请求封装成一个对象,从而让我们可用不同的请求、队列请求、或者日志请求。这样,命令的发出者和命令的执行者可以解耦,提高系统的灵活性。

实际使用场景:

假设我们正在开发一个智能家居系统,用户可以通过一个智能遥控器(RemoteControl)向家庭影院的各个设备(如电视、音响等)发送命令(如开关、调节音量等)。使用命令模式可以很好地设计这个系统,使得遥控器可以灵活地控制不同设备的不同操作,而且容易扩展新的设备或命令。

直接上代码:

a.抽象命令接口

public interface Command {void execute();void undo();
}

b.具体命令类

public class TVOnCommand implements Command {private Television television;public TVOnCommand(Television tv) {this.television = tv;}@Overridepublic void execute() {television.turnOn();}@Overridepublic void undo() {television.turnOff();}
}

c.接收者类

public class Television {public void turnOn() {System.out.println("TV is on.");}public void turnOff() {System.out.println("TV is off.");}
}

d.请求者(调用者)类

public class RemoteControl {private Command command;public void setCommand(Command command) {this.command = command;}public void pressButton() {command.execute();}public void pressUndoButton() {command.undo();}
}

e.客户端代码

public class CommandPatternDemo {public static void main(String[] args) {Television tv = new Television();Command tvOnCommand = new TVOnCommand(tv);Command tvOffCommand = new TVOffCommand(tv);RemoteControl remoteControl = new RemoteControl();remoteControl.setCommand(tvOnCommand);remoteControl.pressButton(); // 执行打开电视命令remoteControl.setCommand(tvOffCommand);remoteControl.pressUndoButton(); // 执行撤销命令,关闭电视}
}

总结
在这个例子中,命令模式通过将动作请求封装成命令对象,实现了发送者和接收者的解耦。这样,我们不仅可以灵活地增加新的命令或接收者,而且可以通过增加新的命令类来支持撤销操作,而不需要修改现有类的代码。此外,命令模式还便于实现日志、事务等功能,因为它提供了一种统一的处理请求的方式。

3.解释器模式(Interpreter)

概念:

它定义了如何使用表达式来解释一个语言中的句子。这种模式实现了文法表达式和其在解释器中的表示,使我们能够对这些句子进行解释和计算。解释器模式通常用于编译器、运算表达式解析、符号处理系统等领域。

实际使用场景:

假设我们正在开发一个简单的计算器程序,它能够解析和计算算术表达式(仅包含加减乘除四则运算)。使用解释器模式,我们可以定义一个表达式接口和一系列实现该接口的具体表达式类,用于解释和计算输入的算术表达式。

直接上代码:

a.抽象表达式

public interface Expression {int interpret();
}

b.终结符表达式

public class TerminalExpression implements Expression {private int value;public TerminalExpression(int value) {this.value = value;}@Overridepublic int interpret() {return value;}
}

c.非终结符表达式

public class PlusExpression implements Expression {private Expression left, right;public PlusExpression(Expression left, Expression right) {this.left = left;this.right = right;}@Overridepublic int interpret() {return left.interpret() + right.interpret();}
}
public class MinusExpression implements Expression {private Expression left, right;public MinusExpression(Expression left, Expression right) {this.left = left;this.right = right;}@Overridepublic int interpret() {return left.interpret() - right.interpret();}
}

d.客户端代码

public class InterpreterPatternDemo {public static void main(String[] args) {Expression five = new TerminalExpression(5);Expression three = new TerminalExpression(3);Expression plus = new PlusExpression(five, three);Expression two = new TerminalExpression(2);Expression minus = new MinusExpression(plus, two);System.out.println("Result of (5 + 3) - 2: " + minus.interpret()); // 输出结果}
}

解释
在这个例子中,我们通过解释器模式定义了一个简单的算术表达式解释器。TerminalExpression类代表了数值(终结符表达式),而PlusExpression和MinusExpression类分别代表了加法和减法操作(非终结符表达式)。客户端代码通过组合这些表达式类实例,构建了一个表达式树来表示(5 + 3) - 2这个算术表达式,然后调用interpret方法来计算表达式的值。

解释器模式适合于那些语言简单且易于用规则表达的问题。对于复杂的语言或者频繁变化的文法规则,解释器模式的维护成本可能会比较高。

4.迭代器模式(Iterator)

概念:

它提供了一种访问集合元素的方式,而又不暴露集合的内部结构。迭代器模式定义了一个迭代器接口,该接口负责遍历集合中的元素,这样就可以不依赖于集合的具体实现来访问集合中的元素。

实际使用场景:

假设我们正在开发一个图书管理系统,系统中包含多个书架,每个书架上摆放着若干本书。为了方便地遍历所有书架上的书籍,我们可以使用迭代器模式来设计这个系统,使得客户端代码无需了解书架的内部结构就能遍历所有书籍。

直接上代码:

a.抽象迭代器接口

public interface Iterator<T> {boolean hasNext();T next();
}

b.具体迭代器

public class BookShelfIterator implements Iterator<Book> {private final BookShelf bookShelf;private int index;public BookShelfIterator(BookShelf bookShelf) {this.bookShelf = bookShelf;this.index = 0;}@Overridepublic boolean hasNext() {return index < bookShelf.getLength();}@Overridepublic Book next() {if (!hasNext()) throw new NoSuchElementException();return bookShelf.getBookAt(index++);}
}

c.聚集接口

public interface Aggregate<T> {Iterator<T> iterator();
}

d.具体聚集

public class BookShelf implements Aggregate<Book> {private final List<Book> books;private int last = 0;public BookShelf(int maxsize) {this.books = new ArrayList<>(maxsize);}public Book getBookAt(int index) {return books.get(index);}public void appendBook(Book book) {if (last >= books.size()) {books.add(book);} else {books.set(last, book);}last++;}public int getLength() {return books.size();}@Overridepublic Iterator<Book> iterator() {return new BookShelfIterator(this);}
}

e.具体元素

public class Book {private String name;public Book(String name) {this.name = name;}public String getName() {return name;}
}

f.客户端代码

public class IteratorPatternDemo {public static void main(String[] args) {BookShelf bookShelf = new BookShelf(4);bookShelf.appendBook(new Book("Design Patterns"));bookShelf.appendBook(new Book("Effective Java"));bookShelf.appendBook(new Book("Clean Code"));Iterator<Book> it = bookShelf.iterator();while (it.hasNext()) {Book book = it.next();System.out.println(book.getName());}}
}

解释
在这个例子中,BookShelf类实现了Aggregate接口,并提供了iterator()方法来返回一个BookShelfIterator实例,该迭代器负责遍历书架上的书籍。客户端代码通过调用iterator()方法获得迭代器,并使用迭代器的hasNext()和next()方法来遍历所有的书籍。迭代器模式使得遍历集合的操作与集合的具体实现相分离,提高了代码的灵活性和可维护性。

好了以上就是行为型设计模式的4种具体设计模式的使用场景;第二,第三部分下期见.

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

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

相关文章

【机器学习】基于RoBERTa模型的句子嵌入实践

1.引言 1.1.RoBERTa模型开发背景 BERT模型自发布以来&#xff0c;就以其卓越的性能和广泛的应用领域&#xff0c;在NLP领域引起了巨大的轰动。BERT通过预训练大量文本数据&#xff0c;学习到了丰富的语言表示&#xff0c;并在多个NLP任务上取得了显著的效果提升。然而&#x…

WebRTC AudioProcessing 移植调试

ref&#xff1a; https://zhuanlan.zhihu.com/p/416984089 webRTC-audio-processing 编译-CSDN博客 webrtc-audio-processing pulseaudio最新版本1.0交叉编译到ARM_webrtc-audio-processing demo-CSDN博客 PulseAudio / webrtc-audio-processing GitLab 移植webrtc-audio…

Swift开发——弱占用

自动引用计数(Automatic Reference Counting&#xff0c;ARC)&#xff0c;是Swift语言管理类的实例的方式。当创建某个类的一个新实例后&#xff0c;ARC自动为新实例分配内存空间&#xff0c;用于保存实例的类型和存储属性&#xff0c;当将该实例赋给常量、变量或其他实例的属性…

npm install 安装不成功,node-sass缺失,提示python环境缺失的解决办法

npm install 安装不成功的原因 是因为缺少python的环境 解决方法&#xff1a; 1、去官网下载 https://www.python.org/downloads/release&#xff0c;注意安装3.6版本以上还是会有问题&#xff0c;建议安装3.6版本以上的&#xff0c;我选择安装的是3.9.6&#xff0c;对应的下载…

numpy用savez_compressed压缩数据

[1] 展示了用 scipy.io.savemat 压缩数据的写法&#xff0c;且在压缩二进制数据时优于 numpy.packbits。其实 numpy.savez_compressed 也能压缩&#xff0c;本文记录用之存压缩数据的写法&#xff0c;并比较其与 numpy.save 和 scipy.io.savemat 压缩效果。 用到 TotalSegment…

京东h5st4.73

声明 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; lianxi a15018601872 …

客观评价,可道云teamOS搭建的企业网盘,如Windows本地电脑一般的使用体验真的蛮不错

不管是企业网盘还是私有网盘&#xff0c;简单易用一直是我比较在意的。快速能上手使用&#xff0c;甚至不需要习惯一套新的操作逻辑&#xff0c;代表着不需要学习适应&#xff0c;能够迅速投入正常使用。 在这个过程中&#xff0c;可道云teamos以其Windows电脑般的流畅体验&am…

【AI】通义千问使用指南:让你快速上手,成为问题解决高手!

大家好&#xff0c;我是木头左。 近日&#xff0c;继文心一言和讯飞星火之后&#xff0c;阿里虽迟但到&#xff0c;直接宣布开源两款“通义千问”大模型。作为国内首个开源且可商用的人工智能大模型&#xff0c;这会给我们带来哪些变化呢&#xff1f; 如何申请阿里通义千问&am…

铁路定向声波冲击波智能驱鸟器

对于铁路系统来说&#xff0c;鸟类活动会带来潜在的安全隐患。铁路沿线的接触网、电杆等设备&#xff0c;是鸟类筑巢的理想场所&#xff0c;但鸟类在筑巢过程中&#xff0c;常常使用的树枝、铁丝等杂物&#xff0c;一旦掉落在接触网设备上&#xff0c;就可能造成带电体与接地侧…

k8s上尝试滚动更新和回滚

滚动更新和回滚 实验目标&#xff1a; 学习如何进行应用的滚动更新和回滚操作。 实验步骤&#xff1a; 创建一个 Deployment。更新 Deployment 的镜像版本&#xff0c;观察滚动更新过程。回滚到之前的版本&#xff0c;验证回滚操作。 今天呢&#xff0c;我们继续来进行我们k…

SIP呼叫截包分析

SIP注册信息 筛选 sip 协议查看截包内容 Request:REGISTER sip:192.168.1.1:5061;transportudp (1 binding) | 1、选择 --> Session Inition Protocol (REGISTER) 展开所有子树查看信息 2、看这个包附近服务器给的回应消息包&#xff0c;如果为registrationReject则是服务…

23.EmbeddedChannel

这个channel可以直接绑定多个handler,不用写服务端代码和客户端代码。便于用于测试。 package com.xkj.bound;import io.netty.buffer.ByteBufAllocator; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.…

newtonsoft.json动态读取json以及动态生成

问题 同一个接口返回不同类型的json&#xff0c;json结构相差比较大转换为C#对象不太合适&#xff0c;想着是否可以动态解析。 newtonsoft类 JTokenType类型 namespace Newtonsoft.Json.Linq {/// <summary>/// Specifies the type of token./// </summary>publ…

聊聊缓存如何进行测试的

为了提升数据访问速度&#xff0c;减少后端服务如数据库的负载&#xff0c;提高系统整体性能&#xff0c;在系统中通常会使用缓存中间件&#xff0c;以下是缓存中间的类型&#xff1a; 缓存中间件类型&#xff1a; 通用内存缓存&#xff1a; Memcached&#xff1a;这是一个高性…

YOLOv10改进 | 主干篇 | YOLOv10引入华为VanillaNet替换Backbone

1. VanillaNet介绍 1.1 摘要: 基础模型的核心是“越多越好”的理念,计算机视觉和自然语言处理领域取得的惊人成功就是例证。 然而,优化的挑战和变压器模型固有的复杂性要求范式向简单性转变。 在这项研究中,我们介绍了 VanillaNet,一种设计优雅的神经网络架构。 通过避免…

图片的dpi分辨率数值能改吗?在线改图片分辨率的方法及步骤

图片分辨率修改是怎么操作的&#xff1f;在使用图片的时候&#xff0c;在很多的情况下需要修改图片分辨率api的数值后才可以正常使用&#xff0c;那么修改图片dpi具体该怎么操作呢&#xff0c;相信有很多小伙伴对于这个问题的处理方法都比较困扰&#xff0c;下面就让小编来给大…

浅谈疫情后IT业的挑战和机会

近期IT业&#xff0c;迎来了久违的寒冬。裁员、找工作难、企业经营艰难.......特别是疫情对全球各行各业产生了深远的影响&#xff0c;但其影响是多方面的&#xff0c;既包括挑战也孕育着机遇。以下是对疫情后IT行业可能的发展趋势和方向的总结. 1、数字化转型加速&#xff1a…

18-云原生监控体系-kube-state-metrics

文章目录 1. 介绍2. kube-state-metrics vs. metrics-server3. 安装3.1. 拉取镜像3.2. 部署到 kubernetes 集群3.2.1 Kubernetes Deployment3.3. 配置到 Prometheus3.3. 自己构建 Docker 镜像3.4. 对于 prometheus-operator/kube-prometeus stack 的用户3.5. helm chart3.5.1. …

插接件焊盘设计

插件孔的标准孔径尺寸&#xff1a;0.60mm(23.6mil)&#xff0c;0.70mm(27.6mil)&#xff0c;0.80mm(31.5mil)&#xff0c;0.90mm(35.4mil)&#xff0c;1.0mm(39.4mil) 插件元器件引线(圆柱形)直径与插件孔直径D之差应为0.40mm(16mil)&#xff5e;0.60mm(24mil)&#xff0c;即插…

mybatisplus sql语句没问题 却命令未正确结束

这里写自定义目录标题 mybatisplus sql语句没问题 却命令未正确结束 mybatisplus sql语句没问题 却命令未正确结束 <select id"statistic" resultType"com.xx.vo.XXVO">select * from tb_test; </select>报错 ‘ 命令未正确结束 ’ 去掉sql语…