策略模式、状态机详细解读
策略模式 (Strategy Pattern)
策略模式 (Strategy Pattern) 是一种行为型设计模式,旨在将一组算法封装成独立的类,使得它们可以相互替换。这种模式让算法的变化不会影响到使用算法的客户,减少了类之间的耦合。策略模式通常用于处理一类问题,但具有多种解决方案时的情况。
一、策略模式的结构
策略模式主要包含以下角色:
- Context(上下文):
- 维护对
Strategy对象的引用。 - 根据实际情况选择和调用特定的策略类。
- 维护对
- Strategy(抽象策略):
- 定义所有策略类的公共接口。通常是一个抽象类或接口,声明一些方法。
- 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. 静态对象的探讨与全局对象的构造顺序 静态对象的探讨 类中的静态成员变量(类类型静态成员) 类中静态变量的声明与定义(类中声明类外定义) #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时,内部视图在水平方向从左往右排列。 2.orientation属性值为vertical时,内部视图在垂直方向从上往下排列。 如果不指定orientation属性,…...
Vue全栈开发旅游网项目(10)-用户管理后端接口开发
1.异步用户登录\登出接口开发 1.设计公共响应数据类型 文件地址: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代码中,经常可以看到native方法,需要查看其对应的C方法,这些方法是一一对应的,对应关系是在jni注册里关联起来的。 比较直观的是这样的例子, Parcel.java //Java层的方法里调用了native方法nativeWriteInt…...
Exploring Defeasible Reasoning in Large Language Models: A Chain-of-Thought A
文章目录 题目摘要简介准备工作数据集生成方法实验结论 题目 探索大型语言模型中的可废止推理:思路链 论文地址:http://collegepublications.co.uk/downloads/LNGAI00004.pdf#page136 摘要 许多大型语言模型 (LLM) 经过大量高质量数据语料库的训练&…...
uniapp在app模式下组件传值
在 UniApp 编译成 App 后,传递参数可以通过多种方式实现,常见的方式有以下几种: 1. 通过 URL 参数传递(适用于 WebView) 如果你的 App 页面通过 WebView 渲染,可以像在 Web 端一样通过 URL 传递参数。例如…...
Docker解决暴露2375端口引发的安全漏洞
docker的暴露api端口2375,没有任何安全防护,我们通过linux系统防火墙(iptables)来进行ip访问限制 # 查看iptables所有规则 iptables -L -nv # 只允许某个ip访问2375端口 iptables -I INPUT -s 127.0.0.1 -p tcp --dport 2375 -j A…...
HTML5+CSS前端开发【保姆级教学】+新闻文章初体验
Hello,各位编程猿们!上一篇文章介绍了前端以及软件的安装,这一篇我们要继续讲解页面更多知识点,教大家做一篇新闻题材的文章 新闻文章 当我们点开浏览器经常看到各种各样的文章,今天我们就来看看大家最喜欢关注的体育…...
『VUE』26. props实现子组件传递数据给父组件(详细图文注释)
目录 本节内容示例代码总结 欢迎关注 『VUE』 专栏,持续更新中 欢迎关注 『VUE』 专栏,持续更新中 本节内容 父组件传子组件–props 子组件传父组件–自定义事件 本节讲子组件传父组件–通过props里的方法传递,就是父亲写了一个函数,给子组件调用,然后…...
RHCE-DNS域名解析服务器
一、DNS简介 DNS ( Domain Name System )是互联网上的一项服务,它作为将域名和 IP 地址相互映射的一个分布式 数据库,能够使人更方便的访问互联网。 DNS 系统使用的是网络的查询,那么自然需要有监听的 port 。 DNS 使…...
移民统计年鉴(1996-2021年)
年鉴中包含了以下几个方面的数据: 移民数量:记录了每年全球移民的总数,以及不同国家和地区的移民流入和流出情况。 移民类型:区分了经济移民、难民、家庭团聚等不同类型的移民。 移民原因:分析了推动移民的各种因素&…...
MFC1(note)
引言 在学习SDK后我们发现,写消息好麻烦,处理消息更麻烦 处理消息效率低发送消息效率低 所以把SDK中这些消息全部封装好 MFC封装了windows 的大部分API 这里说一下QT架构跨平台 MFC用得如何取决于你SDK的水平 创建 如果打开没有MFC 一般勾选以下…...
1.1 关于游戏编程
1.1.1、游戏中客户端和服务器的交互 游戏通常采用客户端-服务器模式。在这种模式下,服务器负责处理游戏的核心逻辑、数据存储和玩家间的交互,而客户端则负责呈现游戏画面、接收玩家输入并与服务器通信。 客户端和服务器的作用和功能 客户端&a…...
光流法与直接法在SLAM中的应用
本文总结视觉SLAM中常用的光流法与直接法 1、Lucas-Kanade光流法 相机所拍摄到的图像随相机视角的变化而变化,这种变化也可以理解为图像中像素的反向移动。“光流”(Optical Flow)是指通过分析连续图像帧来估计场景中像素或特征点的运动的技…...
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…...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...
CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
稳定币的深度剖析与展望
一、引言 在当今数字化浪潮席卷全球的时代,加密货币作为一种新兴的金融现象,正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而,加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下,稳定…...
AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...
push [特殊字符] present
push 🆚 present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中,push 和 present 是两种不同的视图控制器切换方式,它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...
并发编程 - go版
1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...
