当前位置: 首页 > news >正文

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

策略模式 (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 三次握手等)。
  • 工作流系统:如审批流程的状态转换。

总结

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

相关文章:

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

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

OpenWrt广播DNS到客户端

OpenWrt广播DNS到客户端 Network -> Interfaces -> lan ->DHCP Server -> Advanced Settings -> DHCP-Options 设置 6,dns1,dns2 如下图 也可以直接编辑 /etc/config/dhcp config dhcp lan list dhcp_option 6,119.29.29.29,223.5.5.5 #ipv4 option dns 2402:4…...

C++编程技巧与规范-类和对象

类和对象 1. 静态对象的探讨与全局对象的构造顺序 静态对象的探讨 类中的静态成员变量(类类型静态成员) 类中静态变量的声明与定义&#xff08;类中声明类外定义&#xff09; #include<iostream> using namespace std;namespace _nmspl {class A{public:A():m_i(5){…...

AutoHotKey自动热键AHK-正则表达式

在这个软件的操作中,基本都是需要即时的解决一些问题,所以对字符串的操作是比较多的,所以正则的使用还是比较重要的,接下来我们用一个例子来了解正则表达式的使用 str "7654321" RegExMatch(str, "65(43)(21)", SubPat)str ( str %str% SubPat %SubPa…...

【3D Slicer】的小白入门使用指南四

开源解剖影像浏览工具Open Anatomy Browser使用及介绍 和3D slicer米有太大关系,该工具是网页版影像数据的浏览工具(可以简单理解为网页版的3D slicer) 介绍 ● 开放解剖(OA)浏览器是由神经影像分析中心开发的,基于网络浏览器技术构建的图谱查看器。 ● OA浏览器将解剖模…...

flink同步mysql数据表到pg库

1.关闭防火墙和selinux systemctl stop firewalld systemctl disable firewalld systemctl status firewalldvi /etc/selinux/config 修改为disabled2.安装java8 yum list java-1.8* yum install java-1.8.0-openjdk* -yjava -version3.下载和部署postgresql 下载地址&#…...

AndroidStudio-常用布局

一、线性布局LinearLayout 线性布局内部的各视图有两种排列方式: 1.orientation属性值为horizontal时&#xff0c;内部视图在水平方向从左往右排列。 2.orientation属性值为vertical时&#xff0c;内部视图在垂直方向从上往下排列。 如果不指定orientation属性&#xff0c;…...

Vue全栈开发旅游网项目(10)-用户管理后端接口开发

1.异步用户登录\登出接口开发 1.设计公共响应数据类型 文件地址&#xff1a;utils/response404.py from django.http import JsonResponseclass BadRequestJsonResponse(JsonResponse):status_code 400def __init__(self, err_list, *args, **kwargs):data {"error_c…...

[Android]查找java类中声明为native方法的具体实现方法

在android代码中&#xff0c;经常可以看到native方法&#xff0c;需要查看其对应的C方法&#xff0c;这些方法是一一对应的&#xff0c;对应关系是在jni注册里关联起来的。 比较直观的是这样的例子&#xff0c; Parcel.java //Java层的方法里调用了native方法nativeWriteInt…...

Exploring Defeasible Reasoning in Large Language Models: A Chain-of-Thought A

文章目录 题目摘要简介准备工作数据集生成方法实验结论 题目 探索大型语言模型中的可废止推理&#xff1a;思路链 论文地址&#xff1a;http://collegepublications.co.uk/downloads/LNGAI00004.pdf#page136 摘要 许多大型语言模型 (LLM) 经过大量高质量数据语料库的训练&…...

uniapp在app模式下组件传值

在 UniApp 编译成 App 后&#xff0c;传递参数可以通过多种方式实现&#xff0c;常见的方式有以下几种&#xff1a; 1. 通过 URL 参数传递&#xff08;适用于 WebView&#xff09; 如果你的 App 页面通过 WebView 渲染&#xff0c;可以像在 Web 端一样通过 URL 传递参数。例如…...

Docker解决暴露2375端口引发的安全漏洞

docker的暴露api端口2375&#xff0c;没有任何安全防护&#xff0c;我们通过linux系统防火墙&#xff08;iptables&#xff09;来进行ip访问限制 # 查看iptables所有规则 iptables -L -nv # 只允许某个ip访问2375端口 iptables -I INPUT -s 127.0.0.1 -p tcp --dport 2375 -j A…...

HTML5+CSS前端开发【保姆级教学】+新闻文章初体验

Hello&#xff0c;各位编程猿们&#xff01;上一篇文章介绍了前端以及软件的安装&#xff0c;这一篇我们要继续讲解页面更多知识点&#xff0c;教大家做一篇新闻题材的文章 新闻文章 当我们点开浏览器经常看到各种各样的文章&#xff0c;今天我们就来看看大家最喜欢关注的体育…...

『VUE』26. props实现子组件传递数据给父组件(详细图文注释)

目录 本节内容示例代码总结 欢迎关注 『VUE』 专栏&#xff0c;持续更新中 欢迎关注 『VUE』 专栏&#xff0c;持续更新中 本节内容 父组件传子组件–props 子组件传父组件–自定义事件 本节讲子组件传父组件–通过props里的方法传递,就是父亲写了一个函数,给子组件调用,然后…...

RHCE-DNS域名解析服务器

一、DNS简介 DNS &#xff08; Domain Name System &#xff09;是互联网上的一项服务&#xff0c;它作为将域名和 IP 地址相互映射的一个分布式 数据库&#xff0c;能够使人更方便的访问互联网。 DNS 系统使用的是网络的查询&#xff0c;那么自然需要有监听的 port 。 DNS 使…...

移民统计年鉴(1996-2021年)

年鉴中包含了以下几个方面的数据&#xff1a; 移民数量&#xff1a;记录了每年全球移民的总数&#xff0c;以及不同国家和地区的移民流入和流出情况。 移民类型&#xff1a;区分了经济移民、难民、家庭团聚等不同类型的移民。 移民原因&#xff1a;分析了推动移民的各种因素&…...

MFC1(note)

引言 在学习SDK后我们发现&#xff0c;写消息好麻烦&#xff0c;处理消息更麻烦 处理消息效率低发送消息效率低 所以把SDK中这些消息全部封装好 MFC封装了windows 的大部分API 这里说一下QT架构跨平台 MFC用得如何取决于你SDK的水平 创建 如果打开没有MFC 一般勾选以下…...

1.1 关于游戏编程

1.1.1、游戏中客户端和服务器的交互 游戏通常采用客户端-服务器模式‌。在这种模式下&#xff0c;服务器负责处理游戏的核心逻辑、数据存储和玩家间的交互&#xff0c;而客户端则负责呈现游戏画面、接收玩家输入并与服务器通信‌。 客户端和服务器的作用和功能 ‌客户端‌&a…...

光流法与直接法在SLAM中的应用

本文总结视觉SLAM中常用的光流法与直接法 1、Lucas-Kanade光流法 相机所拍摄到的图像随相机视角的变化而变化&#xff0c;这种变化也可以理解为图像中像素的反向移动。“光流”&#xff08;Optical Flow&#xff09;是指通过分析连续图像帧来估计场景中像素或特征点的运动的技…...

C++模板特化实战:在使用开源库boost::geometry::index::rtree时,用特化来让其支持自己的数据类型

用自己定义的数据结构作为rtree的key。 // rTree的key struct OverlapKey {using BDPoint boost::geometry::model::point<double, 3, boost::geometry::cs::cartesian>; //双精度的点using MyRTree boost::geometry::index::rtree<OverlapKey, boost::geometry::in…...

【杂谈】-递归进化:人工智能的自我改进与监管挑战

递归进化&#xff1a;人工智能的自我改进与监管挑战 文章目录 递归进化&#xff1a;人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管&#xff1f;3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统&#xff0c;智慧工地全套源码&#xff0c;java版智慧工地源码&#xff0c;支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求&#xff0c;提供“平台网络终端”的整体解决方案&#xff0c;提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

高危文件识别的常用算法:原理、应用与企业场景

高危文件识别的常用算法&#xff1a;原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件&#xff0c;如包含恶意代码、敏感数据或欺诈内容的文档&#xff0c;在企业协同办公环境中&#xff08;如Teams、Google Workspace&#xff09;尤为重要。结合大模型技术&…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?

Redis 的发布订阅&#xff08;Pub/Sub&#xff09;模式与专业的 MQ&#xff08;Message Queue&#xff09;如 Kafka、RabbitMQ 进行比较&#xff0c;核心的权衡点在于&#xff1a;简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...

return this;返回的是谁

一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请&#xff0c;不同级别的经理有不同的审批权限&#xff1a; // 抽象处理者&#xff1a;审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...

人工智能--安全大模型训练计划:基于Fine-tuning + LLM Agent

安全大模型训练计划&#xff1a;基于Fine-tuning LLM Agent 1. 构建高质量安全数据集 目标&#xff1a;为安全大模型创建高质量、去偏、符合伦理的训练数据集&#xff0c;涵盖安全相关任务&#xff08;如有害内容检测、隐私保护、道德推理等&#xff09;。 1.1 数据收集 描…...

日常一水C

多态 言简意赅&#xff1a;就是一个对象面对同一事件时做出的不同反应 而之前的继承中说过&#xff0c;当子类和父类的函数名相同时&#xff0c;会隐藏父类的同名函数转而调用子类的同名函数&#xff0c;如果要调用父类的同名函数&#xff0c;那么就需要对父类进行引用&#…...

JavaScript 标签加载

目录 JavaScript 标签加载script 标签的 async 和 defer 属性&#xff0c;分别代表什么&#xff0c;有什么区别1. 普通 script 标签2. async 属性3. defer 属性4. type"module"5. 各种加载方式的对比6. 使用建议 JavaScript 标签加载 script 标签的 async 和 defer …...

python读取SQLite表个并生成pdf文件

代码用于创建含50列的SQLite数据库并插入500行随机浮点数据&#xff0c;随后读取数据&#xff0c;通过ReportLab生成横向PDF表格&#xff0c;包含格式化&#xff08;两位小数&#xff09;及表头、网格线等美观样式。 # 导入所需库 import sqlite3 # 用于操作…...