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

前言
行为型设计模式实际使用场景第三部分;

1.状态模式(State)

概念:

它允许对象在其内部状态改变时改变它的行为,对象看起来好像修改了它的类。这种模式主要用于当一个对象的行为依赖于它的状态(对象的状态改变,行为也随之改变)并且它必须在运行时根据状态改变它的行为。

实际使用场景:

假设我们在开发一款简单的ATM机软件,ATM机有多种状态,如空闲、用户认证中、取款、存款、退出等。每种状态下ATM机的行为不同,比如在空闲状态时可以插入银行卡,在取款状态时可以输入取款金额。使用状态模式可以很好地管理这些状态变化及其对应的行为。

直接上代码:

a.抽象状态接口

public interface ATMState {void insertCard();void ejectCard();void insertPin(int pin);void requestCash(int amount);
}

b.具体状态类

public class HasCardState implements ATMState {private ATMContext atmContext;public HasCardState(ATMContext context) {this.atmContext = context;}@Overridepublic void insertCard() {System.out.println("Card is already inserted.");}@Overridepublic void ejectCard() {System.out.println("Ejecting the card...");atmContext.setState(atmContext.getNoCardState());}@Overridepublic void insertPin(int pin) {if (pin == 1234) {System.out.println("Correct PIN, proceeding...");atmContext.setState(atmContext.getHasPinState());} else {System.out.println("Incorrect PIN. Please try again.");}}@Overridepublic void requestCash(int amount) {System.out.println("Please enter your PIN first.");}
}

c.上下文类

public class ATMContext {private ATMState noCardState;private ATMState hasCardState;private ATMState hasPinState;private ATMState dispensingCashState;private ATMState currentState;public ATMContext() {noCardState = new NoCardState(this);hasCardState = new HasCardState(this);hasPinState = new HasPinState(this);dispensingCashState = new DispensingCashState(this);currentState = noCardState;}public void setState(ATMState state) {this.currentState = state;}public ATMState getState() {return currentState;}// 提供对外的接口,由当前状态决定行为public void insertCard() {currentState.insertCard();}public void ejectCard() {currentState.ejectCard();}public void insertPin(int pin) {currentState.insertPin(pin);}public void requestCash(int amount) {currentState.requestCash(amount);}
}

d.客户端代码

public class StatePatternDemo {public static void main(String[] args) {ATMContext atm = new ATMContext();atm.insertCard();atm.insertPin(1234);atm.requestCash(100);atm.ejectCard();}
}

说明
在这个例子中,状态模式使得自动贩卖机的行为可以根据其当前状态动态变化,而不需要在ATMContext类中编写复杂的条件逻辑来判断每一步应该做什么。如果需要增加新的状态或修改已有状态的行为,只需添加或修改相应的状态类,而不影响到其他状态或ATMContext类,这大大提高了系统的可维护性和可扩展性。

2.策略模式(Strategy)

概念:

它使你能在运行时改变对象的行为。在策略模式中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为模式。

实际使用场景:

假设我们正在开发一个电商网站的订单结算系统,该系统需要根据用户选择的配送方式(如普通快递、次日达、自提等)来计算不同的运费。这是一个非常适合使用策略模式的场景,因为每种配送方式的运费计算规则不同,但它们都遵循一个共同的接口。

直接上代码:

a.抽象策略接口

public interface ShippingStrategy {double calculateShippingCost(double weight);
}

b.具体策略类

public class RegularShippingStrategy implements ShippingStrategy {@Overridepublic double calculateShippingCost(double weight) {return weight * 0.05; // 假设普通快递费用是重量的5%}
}
public class ExpressShippingStrategy implements ShippingStrategy {@Overridepublic double calculateShippingCost(double weight) {return weight * 0.1 + 20; // 假设次日达费用是重量的10%加上固定费用20元}
}

c.上下文类

public class Order {private double weight;private ShippingStrategy shippingStrategy;public Order(double weight) {this.weight = weight;}public void setShippingStrategy(ShippingStrategy strategy) {this.shippingStrategy = strategy;}public double calculateTotalCost() {double shippingCost = shippingStrategy.calculateShippingCost(weight);// 假设还有其他成本,如商品价格等,这里简化处理return shippingCost; }
}

d.客户端代码

public class StrategyPatternDemo {public static void main(String[] args) {Order order = new Order(5); // 假设订单重量为5千克// 用户选择了次日达order.setShippingStrategy(new ExpressShippingStrategy());System.out.println("Express shipping cost: " + order.calculateTotalCost());// 用户改选普通快递order.setShippingStrategy(new RegularShippingStrategy());System.out.println("Regular shipping cost: " + order.calculateTotalCost());}
}

说明
在这个例子中,ShippingStrategy接口定义了不同的运费计算策略,而Order类根据用户选择的策略动态调整其运费计算行为。如果未来需要增加新的配送方式,只需添加新的策略类实现ShippingStrategy接口,然后在上下文中设置即可,无需修改现有代码,这极大地提高了系统的灵活性和扩展性。

3.模板方法模式(Template Method)

概念:

它定义了一个操作中的算法骨架,而将一些步骤延迟到子类中实现。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

实际使用场景:

假设我们正在开发一个报告生成系统,系统需要支持多种类型的报告(如PDF报告、HTML报告等),虽然每种报告的生成流程大体相同(比如初始化、获取数据、格式化数据、输出报告),但是具体实现细节各不相同。这时,可以使用模板方法模式来定义报告生成的基本步骤,而将具体实现留给子类完成。

直接上代码:

a.抽象类(定义模板方法)

public abstract class ReportGenerator {// 模板方法,定义了报告生成的步骤public final void generateReport() {initialize();fetchData();formatData();outputReport();}// 具体方法,所有子类共有的实现private void initialize() {System.out.println("Initializing report generation...");}// 抽象方法,由子类实现protected abstract void fetchData();// 抽象方法,由子类实现protected abstract void formatData();// 具体方法,所有子类共有的实现private void outputReport() {System.out.println("Outputting the report...");}
}

b.具体子类

public class PDFReportGenerator extends ReportGenerator {@Overrideprotected void fetchData() {System.out.println("Fetching data for PDF report...");}@Overrideprotected void formatData() {System.out.println("Formatting data into PDF format...");}
}
public class HTMLReportGenerator extends ReportGenerator {@Overrideprotected void fetchData() {System.out.println("Fetching data for HTML report...");}@Overrideprotected void formatData() {System.out.println("Formatting data into HTML format...");}
}

c.客户端代码

public class TemplateMethodPatternDemo {public static void main(String[] args) {ReportGenerator pdfGen = new PDFReportGenerator();pdfGen.generateReport();System.out.println("\n");ReportGenerator htmlGen = new HTMLReportGenerator();htmlGen.generateReport();}
}

说明
在这个例子中,ReportGenerator抽象类定义了报告生成的模板方法generateReport(),它是一个固定流程,包括初始化、获取数据、格式化数据和输出报告四个步骤。其中,fetchData()和formatData()是抽象方法,由具体的子类(如PDFReportGenerator和HTMLReportGenerator)实现,以适应不同类型的报告生成需求。这样,模板方法模式既保证了算法的整体结构稳定,又允许子类灵活地重定义部分步骤,提高了代码的复用性和扩展性。

4.访问者模式(Visitor)

概念:

它允许你定义一个作用于某对象结构中的各个元素的操作,而无需改变它们的类。这种模式适用于需要对元素执行许多不同类型的复杂操作的情况,且这些操作在不断变化或增加时,可以方便地扩展。

实际使用场景:

设想一个电商系统,需要统计不同类型商品(如书籍、电子产品)的总价和总重量,但商品类型和统计需求可能会随时间增长。为了不修改商品类,可以使用访问者模式来动态添加新的统计功能。

直接上代码:

a.定义元素接口和具体元素

// 商品元素接口,声明接受访问者的方法
public interface Product {void accept(Visitor visitor);
}
// 具体商品类 - 书籍
public class Book implements Product {private String title;private double price;private double weight;public Book(String title, double price, double weight) {this.title = title;this.price = price;this.weight = weight;}public void accept(Visitor visitor) {visitor.visit(this);}// 获取价格和重量的方法public double getPrice() { return price; }public double getWeight() { return weight; }
}

b.访问者接口和具体访问者

// 访问者接口,声明访问商品的方法
public interface Visitor {void visit(Book book);// 如果有其他商品类型,这里会添加相应的方法,如visit(Electronics electronics)...
}
// 具体访问者 - 统计价格和重量
public class StatisticsVisitor implements Visitor {private double totalCost = 0.0;private double totalWeight = 0.0;@Overridepublic void visit(Book book) {totalCost += book.getPrice();totalWeight += book.getWeight();}// 对于其他商品类型的visit方法...// 提供获取统计结果的方法public double getTotalCost() { return totalCost; }public double getTotalWeight() { return totalWeight; }
}

c.客户端代码

public class VisitorPatternDemo {public static void main(String[] args) {// 创建商品集合List<Product> products = new ArrayList<>();products.add(new Book("Effective Java", 50.0, 1.2));products.add(new Book("Clean Code", 40.0, 0.9));// 假设还有其他商品如电子产品...// 创建访问者Visitor statisticsVisitor = new StatisticsVisitor();// 遍历商品,让每个商品接受访问者的访问for (Product product : products) {product.accept(statisticsVisitor);}// 输出统计结果System.out.println("Total cost: " + statisticsVisitor.getTotalCost());System.out.println("Total weight: " + statisticsVisitor.getTotalWeight());}
}

说明
在这个例子中,Product接口和其实现类(如Book)代表了元素,它们都包含了一个accept方法用于接收访问者。Visitor接口和实现类(如StatisticsVisitor)定义了对元素的操作。通过这种方式,可以很容易地添加新的统计逻辑(比如计算平均价格的访问者),而不必修改商品类,这大大提高了系统的可维护性和扩展性。

好了以上就是行为型设计模式的4种具体设计模式的使用场景;到此23种设计模式场景应用全部解析完毕,希望能给同学们带来帮助.
如果觉得有帮助的话动下鼠标点个赞,3Q啦,下班回家做饭喽OVO

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

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

相关文章

专业技能篇--算法

文章目录 前言经典算法思想总结一、贪心算法二、动态规划三、回溯算法四、分治算法 前言 这篇简单理解一些常见的算法。如果面试的时候问到相关的算法&#xff0c;能够应付一二。 经典算法思想总结 一、贪心算法 思想&#xff1a;贪心算法是一种在每一步选择中都采取在当前状…

Python——Gradio

什么是 Gradio&#xff1f; Gradio 是一个开源的 Python 库&#xff0c;用于创建用户友好的、交互式的网页界面。这个界面可以用来展示和测试机器学习模型&#xff0c;或者任何需要用户输入的 Python 应用程序。Gradio 的目标是让开发者快速地将他们的机器学习模型部署为可供他…

Vue CLI,Vue Router,Vuex

前言 Vue CLI、Vue Router 和 Vuex 都是 Vue.js 生态系统中的重要组成部分&#xff0c;它们在构建 Vue 应用程序时扮演着关键角色。 Vue CLI Vue CLI 介绍 Vue CLI 是 Vue.js 的官方命令行工具&#xff0c;用于快速搭建 Vue.js 项目。它提供了一个图形界面&#xff08;通过…

Effective C++ 改善程序与设计的55个具体做法笔记与心得 1

一. 让自己习惯C 1. 视C为一个语言联邦 2. 尽量以const, enum, inline替换#define #define CALL_WITH_MAX(a,b) f((a) > (b) ? (a) : (b))int a 5 , b 0;CALL_WITH_MAX(a,b); // a 6, b 0 CALL_WITH_MAX(a,b10); // a 8, b 0你观察到的这个现象是由于宏替换(C prep…

工程打包与运行

黑马程序员Spring Boot2 文章目录 先点击cean&#xff0c;确保打包之前是个干净的环境点击package进行打包&#xff0c;打包成功之后可以看到target文件夹下的文件 到项目目录下使用终端打开&#xff0c;并使用以下命令运行打包好的程序 如果遇到没有主清单属性的问题&#xff…

搜维尔科技邀您共赴2024第四届轨道车辆工业设计国际研讨会

会议内容 聚焦“创新、设计、突破”&#xff0c;围绕“面向生命健康、可持续发展的轨道交通系统” 为主题&#xff0c;从数字化、智能化、人性化、绿色发展等方面&#xff0c;探索轨道交通行业的设计新趋势及发展新机遇。 举办时间 2024年7月10日-12日 举办地点 星光岛-青岛融…

5.音视频基础 FLV

目录 简说FLV FLV Header FLV Body Tag Header ​编辑Tag Data Audio Data Video Data Script Data 简说FLV FLV格式可以包含音频、视频和文本数据&#xff0c;并且可以在网络上进行流媒体传输。优点是文件大小较小&#xff0c;压缩效率高&#xff0c;并且可以在较低…

ROS 激光雷达

ROS 激光雷达 基本工作原理 激光雷达&#xff08;LIDAR&#xff0c;Light Detection and Ranging&#xff09;是一种用于测量距离的远程感应技术。它通过向目标发射激光并分析反射回来的光来测量目标与激光发射源之间的距离。激光雷达广泛应用于多种领域&#xff0c;包括地理…

feign原理

Feign远程调用&#xff0c;核心就是通过一系列的封装和处理&#xff0c;将以JAVA注解的方式定义的远程调用API接口&#xff0c;最终转换成为HTTP的请求形式&#xff0c;然后将HTTP的请求的响应结果&#xff0c;解码成JAVA Bean&#xff0c;放回给调用者。 流程 FeignClient远程…

Vue3 之 Pinia 服务端渲染 (SSR) (九)

Pinia SSR概述 Pinia是一个用于Vue.js的状态管理库&#xff0c;它支持服务端渲染(SSR)。在SSR中&#xff0c;页面在服务器端渲染成HTML字符串&#xff0c;然后发送到客户端&#xff0c;从而提升首屏加载速度和SEO优化。Pinia通过其设计使得在SSR环境下也能轻松使用和管理状态。…

WiFi/BLE芯片(1):英飞凌

前言: 大部分客户很少直接接触到WiFi/Bluetooth的芯片,一般是直接封装到了模块中,隔了一层。具体到芯片而言,WiFi/BLE芯片,芯片厂家有:Qualcomm高通、broadcom博通、Infineon英飞凌、Nordic诺迪科、Espressof乐鑫等。而英飞凌这块产品也是很丰富的,低功耗、距离等性能指…

飞创直线模组厂家,为高精度运动系统提供直驱技术解决方案

飞创Faster motion是国内一家专业的直线模组厂家&#xff0c;致力于研发、设计、生产超长行程、超高速度、超高精度、超重负载以及速度平稳的单轴和多轴直线电机模组&#xff0c;为高速、高精度运动平台提供直驱技术解决方案。 飞创直线模组其生产的单轴、双轴、龙门、多轴模组…

Spring Boot究竟是如何进行自动配置的!

我们都知道 SpringBoot 是要比原始的 SpringMVC 这些好用的&#xff0c;毕竟如果经历过最早的 SSM 模式的开发的话&#xff0c;一定对那些大批量的繁琐的配置文件印象颇深&#xff0c;因为之前使用 SSM 框架来进行开发的时候&#xff0c;那配置文件多的让人心态都容易崩溃&…

化工电力系统RFID无线测温技术的重要性。

在现代工业体系中&#xff0c;化工电力系统的安全与效率对于整个生产链的顺畅运行至关重要。在日常工作中,由于设备制造的原因,设备受环境污染的原因、设备长期运行、严重超载运行、触点氧化、电弧冲击等原因造接触电阻增大,因此在运行时往往不断发热,温度不断上升,给设备安全运…

Leetcode Hot100之双指针

1. 移动零 题目描述 给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。解题思路 双指针遍历一遍即可解决: 我们定义了两个指针 i 和 j&#xf…

C++ Windows Hook使用

GitHub - microsoft/Detours: Detours is a software package for monitoring and instrumenting API calls on Windows. It is distributed in source code form. /*挂载钩子 setdll /d:C:\Users\g\source\repos\LotTest\Release\lotDll.dll C:\Users\g\source\repos\LotTest…

Java特性之设计模式【访问者模式】

一、访问者模式 概述 在访问者模式&#xff08;Visitor Pattern&#xff09;中&#xff0c;我们使用了一个访问者类&#xff0c;它改变了元素类的执行算法。通过这种方式&#xff0c;元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行为型模式。根据模式&…

WPF三方UI库全局应用MessageBox样式(.NET6版本)

一、问题场景 使用HandyControl简写HC 作为基础UI组件库时&#xff0c;希望系统中所有的MessageBox 样式都使用HC的MessageBox&#xff0c;常规操作如下&#xff1a; 在对应的xxxx.cs 顶部使用using 指定特定类的命名空间。 using MessageBox HandyControl.Controls.Message…

js语法---理解反射Reflect对象和代理Proxy对象

Reflect 基本要点 反射&#xff1a;reflect是一个内置的全局对象&#xff0c;它的作用就是提供了一些对象实例的拦截方法&#xff0c;它的用法和Math对象相似&#xff0c;都只有静态方法和属性&#xff0c;同时reflect也没有构造器&#xff0c;无法通过new运算符构建实例对象&…