策略模式、状态机详细解读

策略模式 (Strategy Pattern)

策略模式 (Strategy Pattern) 是一种行为型设计模式,旨在将一组算法封装成独立的类,使得它们可以相互替换。这种模式让算法的变化不会影响到使用算法的客户,减少了类之间的耦合。策略模式通常用于处理一类问题,但具有多种解决方案时的情况。

一、策略模式的结构

策略模式主要包含以下角色:

  1. Context(上下文)
    • 维护对 Strategy 对象的引用。
    • 根据实际情况选择和调用特定的策略类。
  2. Strategy(抽象策略)
    • 定义所有策略类的公共接口。通常是一个抽象类或接口,声明一些方法。
  3. ConcreteStrategy(具体策略)
    • 实现 Strategy 接口的具体类,封装了具体的算法。
二、策略模式的类图
      +---------------+|   Context     |+---------------+|| usesv+---------------+|  Strategy     |+---------------+^|+--------+---------+|                  |
+-----------+   +-------------+
| StrategyA |   | StrategyB   |
+-----------+   +-------------+
三、策略模式的实现(Java 示例)

假设我们要实现一个支付系统,可以支持 支付宝 (Alipay)微信支付 (WeChatPay)银联支付 (UnionPay)

1. 定义策略接口 (Strategy):

interface PaymentStrategy {void pay(int amount);
}

2. 具体策略实现类 (ConcreteStrategy):

// 支付宝支付策略
class AlipayStrategy implements PaymentStrategy {public void pay(int amount) {System.out.println("Using Alipay to pay: " + amount + "元");}
}// 微信支付策略
class WeChatPayStrategy implements PaymentStrategy {public void pay(int amount) {System.out.println("Using WeChatPay to pay: " + amount + "元");}
}// 银联支付策略
class UnionPayStrategy implements PaymentStrategy {public void pay(int amount) {System.out.println("Using UnionPay to pay: " + amount + "元");}
}

3. 定义上下文类 (Context):

class PaymentContext {private PaymentStrategy strategy;// 设置支付策略public void setPaymentStrategy(PaymentStrategy strategy) {this.strategy = strategy;}// 执行支付public void executePayment(int amount) {strategy.pay(amount);}
}

4. 客户端测试代码:

public class StrategyPatternDemo {public static void main(String[] args) {PaymentContext context = new PaymentContext();// 使用支付宝支付context.setPaymentStrategy(new AlipayStrategy());context.executePayment(100);// 使用微信支付context.setPaymentStrategy(new WeChatPayStrategy());context.executePayment(200);// 使用银联支付context.setPaymentStrategy(new UnionPayStrategy());context.executePayment(300);}
}

输出结果:

Using Alipay to pay: 100元
Using WeChatPay to pay: 200元
Using UnionPay to pay: 300元
四、策略模式的优缺点

优点:

  • 开闭原则:可以在不修改原有代码的情况下增加新策略。
  • 可扩展性强:各个策略类可以独立变化。
  • 减少代码冗余:将算法封装成独立的类,有助于复用。

缺点:

  • 增加类数量:如果策略过多,会导致类的数量增加,增加系统复杂性。
  • 客户端需要知道策略:客户端需要理解不同策略的区别,并选择合适的策略。

应用场景:

  • 需要在多种算法之间进行选择时,如不同的排序算法、加密算法等。
  • 需要在运行时动态决定某一行为的具体实现时。
  • 支付系统日志系统数据处理系统 等。

状态机 (State Machine)

状态机 (State Machine),又称为 有限状态机 (Finite State Machine, FSM),是一种用于表示对象状态及其状态转换的模型。它定义了一组状态以及状态之间的转换规则,通过事件触发状态的转变,从而改变对象的行为。

一、状态机的基本概念
  • 状态 (State):系统在任一时刻所处的情况或条件。
  • 事件 (Event):触发状态转换的条件或动作。
  • 转换 (Transition):从一个状态到另一个状态的变化。
  • 动作 (Action):状态转换时执行的操作。
二、状态机的示例

假设我们要实现一个简单的订单管理系统,它包含以下几个状态:

  • 创建 (Created):订单刚创建。
  • 已支付 (Paid):订单已支付。
  • 已发货 (Shipped):订单已发货。
  • 已完成 (Completed):订单已完成。

状态转换图如下:

Created → [支付] → Paid → [发货] → Shipped → [完成] → Completed
三、状态机的实现(Java 示例)

1. 定义状态接口:

interface OrderState {void handleOrder(OrderContext context);
}

2. 具体状态实现类:

// 创建状态
class CreatedState implements OrderState {public void handleOrder(OrderContext context) {System.out.println("订单已创建,等待支付...");context.setState(new PaidState());}
}// 已支付状态
class PaidState implements OrderState {public void handleOrder(OrderContext context) {System.out.println("订单已支付,等待发货...");context.setState(new ShippedState());}
}// 已发货状态
class ShippedState implements OrderState {public void handleOrder(OrderContext context) {System.out.println("订单已发货,等待收货...");context.setState(new CompletedState());}
}// 已完成状态
class CompletedState implements OrderState {public void handleOrder(OrderContext context) {System.out.println("订单已完成!");}
}

3. 定义上下文类 (Context):

class OrderContext {private OrderState state;public OrderContext() {state = new CreatedState(); // 初始状态}public void setState(OrderState state) {this.state = state;}public void next() {state.handleOrder(this);}
}

4. 客户端测试代码:

public class StateMachineDemo {public static void main(String[] args) {OrderContext order = new OrderContext();order.next(); // 订单已创建,等待支付order.next(); // 订单已支付,等待发货order.next(); // 订单已发货,等待收货order.next(); // 订单已完成}
}

输出结果:

订单已创建,等待支付...
订单已支付,等待发货...
订单已发货,等待收货...
订单已完成!
四、状态机的优缺点

优点:

  • 清晰的状态管理:能够清晰地定义对象在不同状态下的行为。
  • 易于维护:将状态与行为封装在一起,代码易于扩展和维护。
  • 提高可读性:通过状态和转换将复杂的业务逻辑简化。

缺点:

  • 类的增加:如果状态过多,会导致类数量增加,增加系统复杂性。
  • 状态切换成本:频繁的状态切换可能会导致性能开销。

应用场景:

  • 订单处理系统:如电商平台中的订单状态管理。
  • 游戏开发:如角色状态(行走、跳跃、攻击等)的管理。
  • 协议解析:如网络协议中的状态管理(TCP 三次握手等)。
  • 工作流系统:如审批流程的状态转换。

总结

  • 策略模式 适用于有多种算法可供选择的场景,能够在运行时灵活选择算法,提高系统的扩展性。
  • 状态机 适合复杂状态管理的场景,能够清晰地定义对象在不同状态下的行为,并有效处理状态之间的转换。
  • 两者虽然解决的问题不同,但在实际应用中可以结合使用,以构建更加灵活和健壮的系统。

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

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

相关文章

Flutter 小技巧之 OverlayPortal 实现自限性和可共享的页面图层

大家对于 Overlay 可能不会陌生,那么 OverlayPortal 呢? 在 Flutter 中可以通过向 MaterialApp 下的 Overlay 添加“图层”,来实现比如「增加一个全局悬浮控件」或者「页面指引」之类的实现,这是因为 Overlay 在 Flutter 里类似于…

FlinkPipelineComposer 详解

FlinkPipelineComposer 详解 原文 背景 在flink-cdc 3.0中引入了pipeline机制,提供了除Datastream api/flink sql以外的一种方式定义flink 任务 通过提供一个yaml文件,描述source sink transform等主要信息 由FlinkPipelineComposer解析&#xff0c…

AutoDL远程连接技巧

写在前面 本次只是个人经验分享 面是我随便复制的 登录指令:ssh -p 38292 rootconnect.c1.seetacloud.com 登录密码:YBjlgzbZNou 在下面图片中:名称可以随便取: 协议一般选择SSH,主机名称就是后面的;用我的…

FPGA学习(10)-数码管

前3节视频目的是实现显示0~F的数码管仿真,后3节是用驱动芯片驱动数码管。 目录 1.数码管显示原理 2.代码过程 2.1仿真结果 3.串行移位寄存器原理 3.1原理 ​编辑 3.2 数据手册 3.3 先行设计思路 4.程序 4.1确定SRCLK的频率 4.2序列计数器 4.3 不同coun…

k8s 1.28.2 集群部署 docker registry 接入 MinIO 存储

文章目录 [toc]docker registry 部署生成 htpasswd 文件生成 secret 文件 生成 registry 配置文件创建 service创建 statefulset创建 ingress验证 docker registry docker registry 监控docker registry ui docker registry dockerfile docker registry 配置文件 S3 storage dr…

软件工程笔记二—— 软件生存期模型

目录 瀑布模型 瀑布模型的特点 阶段间具有顺序性和依赖性。 推迟实现的观点 质量保证的观点 瀑布模型的优点 瀑布模型的缺点 快速原型模型 快速原型模型的优点 快速原型模型的缺点 增量模型 增量模型的优点 增量构件开发 螺旋模型 完整的螺旋模型(顺…

万字长文解读深度学习——生成对抗网络GAN

🌺历史文章列表🌺 深度学习——优化算法、激活函数、归一化、正则化深度学习——权重初始化、评估指标、梯度消失和梯度爆炸深度学习——前向传播与反向传播、神经网络(前馈神经网络与反馈神经网络)、常见算法概要汇总万字长文解读…

【MYSQL】数据库日志 (了解即可)

一、错误日志 可以通过 tail查看文件的日志的,如果发生错误,就会在日志里出现问题。 二、二进制日志(binlog) BINLOG记录了insert delete update 以及 alter create drop 等语句。作用是灾难时的数据恢复,还有就是主…

整理iPhone空间:iphone怎么删除相簿

随着时间的积累,我们的iPhone中不仅会堆积大量照片,还可能会有多个不再需要的相簿。这些相簿不仅占用存储空间,还可能使相册应用变得杂乱无章。本文将探讨iphone怎么删除相簿,并介绍精简iPhone相册的技巧,使你的相册管…

ABAP关于PS模块CJ20N中项目物料的屏幕和字段增强CI_RSADD

网上搜关于CJ20N的屏幕增强,基本都是关于项目定义(CI_PROJ)、项目WBS(CI_PRPS)、项目网络活动工序(CI_AFVU)的字段与屏幕增强,几乎没有关于项目物料(CI_RSADD)的字段屏幕增强,我在这里做一个分享。 主要逻辑:实现badi增强,并自建一个函数组后创建屏幕,在badi里面调用…

Kettle配置数据源错误“Driver class ‘org.gjt.mm.mysql.Driver‘ could not be found”解决记录

问题描述 错误提示:“Driver class ‘org.gjt.mm.mysql.Driver’ could not be found, make sure the ‘MySQL’ driver (jar file) is installed.” 原因分析: 根据错误提示是缺少了相关的数据源连接jar包。 解决方案: 安装对应的Mysql…

基于Python 和 pyecharts 制作招聘数据可视化分析大屏

在本教程中,我们将展示如何使用 Python 和 pyecharts 库,通过对招聘数据的分析,制作一个交互式的招聘数据分析大屏。此大屏将通过不同类型的图表(如柱状图、饼图、词云图等)展示招聘行业、职位要求、薪资分布等信息。 …

人力资源招聘系统的革新之路:从传统到智能的转变

在全球化与数字化交织的今天,企业间的竞争日益激烈,而人才作为企业发展的核心驱动力,其重要性不言而喻。传统的人力资源招聘方式,如依赖纸质简历、人工筛选、面对面面试等,不仅效率低下,且难以精准匹配企业…

UE5 UE4 播放视频没有声音解决

开启AVF插件 在项目设置中,AVF 的调试打开。 在项目设置中,WMF Media 中,allow Non standard Codecs,Low Latency 和 Native Audio Out打开。

sql专题 之 where和join on

文章目录 前言where介绍使用过滤结果集关联两个表 连接外连接内连接自然连接 使用inner join和直接使用where关联两个表的区别总结 前言 从数据库查询数据时,一张表不足以查询到我们想要的数据,更多的时候我们需要联表查询。 联表查询我们一般会使用连接…

如何在CentOS 7上搭建SMB服务

如何在CentOS 7上搭建SMB服务 因项目测试需求,需要自行搭建SMB服务,**SMB(Server Message Block)**协议是一种常用的文件共享方式,它可以让不同操作系统之间共享文件、打印机等资源。本文将带你一步步搭建一个简单的S…

使用CNN进行验证码识别:深度学习与图像预处理教程

验证码(CAPTCHA)广泛用于区分人类和自动化程序(如机器人),通常由扭曲的字母、数字或符号组成。为了实现验证码的自动识别,深度学习尤其是卷积神经网络(CNN)非常有效。本文将带你一起…

STM32 51单片机设计半导体制冷片温控设计

目录 前言 一、本设计主要实现哪些很“开门”功能? 二、电路设计原理图 1.电路图采用Altium Designer进行设计: 三、实物设计图 四、程序源代码设计 五、获取资料内容 前言 基于STM32与51单片机的半导体制冷片温控设计 前言 随着现代工业、医疗…

ssm114基于SSM框架的网上拍卖系统的设计与实现+vue(论文+源码)_kaic

摘 要 随着科学技术的飞速发展,各行各业都在努力与现代先进技术接轨,通过科技手段提高自身的优势,商品拍卖当然也不能排除在外,随着商品拍卖管理的不断成熟,它彻底改变了过去传统的经营管理方式,不仅使商品…

算法每日双题精讲——滑动窗口(长度最小的子数组,无重复字符的最长子串)

🌟快来参与讨论💬,点赞👍、收藏⭐、分享📤,共创活力社区。 🌟 别再犹豫了!快来订阅我们的算法每日双题精讲专栏,一起踏上算法学习的精彩之旅吧!💪…