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

16行为型设计模式——策略模式

一、策略模式简介

策略模式(Strategy Pattern)是一种行为型设计模式,它定义了一系列的算法,将每一个算法封装起来,并使它们可以相互替换。具体的算法选择交由客户端决定,即不同的算法可以在运行时动态地(平滑地)进行替换和管理。

策略:根据形势发展而制定的行动方针和斗争方法;泛指善于灵活运用适当 '眼下情况下的' 斗争方式和方法。

策略模式的结构图

策略模式的组成 

  1. 上下文(Context):持有一个策略的引用,并且可以在运行时更换策略。
  2. 策略接口(Strategy):定义了一个公共的接口,所有的具体策略都实现这个接口。
  3. 具体策略(ConcreteStrategy):实现了策略接口的具体算法。

二、策略模式的设计方法

使用策略模式设计《36计》的23种计策,每一种计策设计成一个单独的类,模拟每一个策略的行为(字符描述)。

 strategy.cpp

#include <iostream>
#include <memory>
#include <map>
#include <string>// 策略接口
class Strategy {
public:virtual ~Strategy() = default;virtual void execute() const = 0;
};// 具体策略
class Strategy1 : public Strategy {
public:void execute() const override {std::cout << "掩盖真实意图,混淆敌人视线,以达到自己的目的。" << std::endl;}
};class Strategy2 : public Strategy {
public:void execute() const override {std::cout << "利用第三方的力量或资源来打击目标。" << std::endl;}
};class Strategy3 : public Strategy {
public:void execute() const override {std::cout << "让敌人疲惫,自己则采取相对轻松的状态来应对。" << std::endl;}
};class Strategy4 : public Strategy {
public:void execute() const override {std::cout << "在敌人危机时刻,乘机夺取利益。" << std::endl;}
};class Strategy5 : public Strategy {
public:void execute() const override {std::cout << "制造假象,引诱敌人到错误的方向上。" << std::endl;}
};class Strategy6 : public Strategy {
public:void execute() const override {std::cout << "制造虚假信息或虚构情况,迷惑敌人。" << std::endl;}
};class Strategy7 : public Strategy {
public:void execute() const override {std::cout << "秘密行动,绕过敌人的防线。" << std::endl;}
};class Strategy8 : public Strategy {
public:void execute() const override {std::cout << "表面友善,实则暗中图谋。" << std::endl;}
};class Strategy9 : public Strategy {
public:void execute() const override {std::cout << "顺势而为,趁机获得附带利益。" << std::endl;}
};class Strategy10 : public Strategy {
public:void execute() const override {std::cout << "通过小动作试探敌人反应,暴露敌人的真实意图。" << std::endl;}
};class Strategy11 : public Strategy {
public:void execute() const override {std::cout << "引开敌人,使其离开本来的位置或目标。" << std::endl;}
};class Strategy12 : public Strategy {
public:void execute() const override {std::cout << "暂时放松对目标的控制,诱使其主动暴露。" << std::endl;}
};class Strategy13 : public Strategy {
public:void execute() const override {std::cout << "用小的代价吸引敌人,为获取更大利益做铺垫。" << std::endl;}
};class Strategy14 : public Strategy {
public:void execute() const override {std::cout << "根据实际情况灵活应对,采取适当的行动。" << std::endl;}
};class Strategy15 : public Strategy {
public:void execute() const override {std::cout << "全面考虑局势,制定整体计划。" << std::endl;}
};class Strategy16 : public Strategy {
public:void execute() const override {std::cout << "客人反过来成为主人,掌握主动权。" << std::endl;}
};class Strategy17 : public Strategy {
public:void execute() const override {std::cout << "虚晃一招,使敌人判断错误,然后在另一方发起攻击。" << std::endl;}
};class Strategy18 : public Strategy {
public:void execute() const override {std::cout << "直接攻击敌人的首领,瓦解其指挥系统。" << std::endl;}
};class Strategy19 : public Strategy {
public:void execute() const override {std::cout << "以替代品欺骗敌人,保全自身利益。" << std::endl;}
};class Strategy20 : public Strategy {
public:void execute() const override {std::cout << "在安全距离观察敌人行动,吃瓜群众。" << std::endl;}
};class Strategy21 : public Strategy {
public:void execute() const override {std::cout << "通过攻击敌人的其他重要目标,迫使敌人撤退。" << std::endl;}
};class Strategy22 : public Strategy {
public:void execute() const override {std::cout << "在无胜算的情况下,选择撤退以保存实力。" << std::endl;}
};class Strategy23 : public Strategy {
public:void execute() const override {std::cout << "抓住敌人的致命弱点,进行精准打击。" << std::endl;}
};// 上下文
class Context {
public:Context(std::unique_ptr<Strategy> strategy) : strategy(std::move(strategy)) {}void setStrategy(std::unique_ptr<Strategy> newStrategy) {strategy = std::move(newStrategy);}void executeStrategy() const {strategy->execute();}private:std::unique_ptr<Strategy> strategy;
};// 策略工厂
class StrategyFactory {
public:using StrategyCreator = std::unique_ptr<Strategy>(*)();static StrategyFactory& getInstance() {static StrategyFactory instance;return instance;}void registerStrategy(const std::string& name, StrategyCreator creator) {creators[name] = creator;}std::unique_ptr<Strategy> createStrategy(const std::string& name) const {auto it = creators.find(name);if (it != creators.end()) {return it->second();}return nullptr;}private:std::map<std::string, StrategyCreator> creators;
};// 注册策略
#define REGISTER_STRATEGY(name, strategyClass) \
namespace { \const bool registered_##strategyClass = \(StrategyFactory::getInstance().registerStrategy(name, []() -> std::unique_ptr<Strategy> { \return std::make_unique<strategyClass>(); \}), true); \
}// 注册所有策略
REGISTER_STRATEGY("瞒天过海", Strategy1)
REGISTER_STRATEGY("借刀杀人", Strategy2)
REGISTER_STRATEGY("以逸待劳", Strategy3)
REGISTER_STRATEGY("趁火打劫", Strategy4)
REGISTER_STRATEGY("声东击西", Strategy5)
REGISTER_STRATEGY("无中生有", Strategy6)
REGISTER_STRATEGY("暗渡陈仓", Strategy7)
REGISTER_STRATEGY("笑里藏刀", Strategy8)
REGISTER_STRATEGY("顺手牵羊", Strategy9)
REGISTER_STRATEGY("打草惊蛇", Strategy10)
REGISTER_STRATEGY("调虎离山", Strategy11)
REGISTER_STRATEGY("欲擒故纵", Strategy12)
REGISTER_STRATEGY("抛砖引玉", Strategy13)
REGISTER_STRATEGY("见机行事", Strategy14)
REGISTER_STRATEGY("统筹全局", Strategy15)
REGISTER_STRATEGY("反客为主", Strategy16)
REGISTER_STRATEGY("声东击西", Strategy17)
REGISTER_STRATEGY("擒贼擒王", Strategy18)
REGISTER_STRATEGY("李代桃僵", Strategy19)
REGISTER_STRATEGY("隔岸观火", Strategy20)
REGISTER_STRATEGY("围魏救赵", Strategy21)
REGISTER_STRATEGY("三十六计,走为上策", Strategy22)
REGISTER_STRATEGY("打蛇打七寸", Strategy23)
// 注册更多策略...// 客户端
int main() {// 客户选择策略std::string strategyName;std::cout << "请选择您的策略(方案): ";std::cin >> strategyName;// 从工厂创建策略auto strategy = StrategyFactory::getInstance().createStrategy(strategyName);if (strategy) {Context context(std::move(strategy));context.executeStrategy();} else {std::cout << "您的36计不存在策略--->"<< strategyName << " ,请纠正或补充哦! " << std::endl;}return 0;
}

运行效果

三、策略模式的应用场景

1. 需要在运行时选择算法或策略

当你的应用程序需要根据不同的条件选择不同的算法或策略时,策略模式可以帮助你将这些算法封装到独立的策略类中,从而在运行时动态地选择和切换策略。例如:

  • 排序算法选择:在一个排序工具中,你可能需要根据数据的大小或性质选择不同的排序算法(如快速排序、归并排序、插入排序等)。
  • 支付处理:一个电商系统可能需要支持多种支付方式(如信用卡、PayPal、银行转账等),用户可以选择不同的支付策略进行支付。

2. 系统中有多个类似的变体

当系统中存在多个类似的变体,且这些变体的行为仅在某些方面有所不同时,策略模式可以帮助你将这些变体的具体实现分离到不同的策略类中。例如:

  • 游戏角色行为:在游戏中,角色可能有不同的攻击策略(如近战攻击、远程攻击、魔法攻击等),这些策略可以作为独立的策略类来实现。
  • 图形渲染:在图形渲染系统中,可以使用不同的渲染策略(如2D渲染、3D渲染、光线追踪等)来处理不同的渲染需求。

3. 需要避免条件语句

当你发现自己在一个类中使用大量的条件语句(如 if-else 或 switch 语句)来选择不同的行为时,策略模式可以帮助你简化代码,将这些条件语句移到策略类中。例如:

  • 文本格式化:一个文档处理程序可能需要根据不同的格式要求(如 Markdown、HTML等)格式化文本。可以使用策略模式来替代复杂的条件判断。
  • 数据压缩:在一个数据处理系统中,根据不同的压缩要求(如 ZIP、RAR、GZIP 等)进行数据压缩时,策略模式可以帮助减少条件语句的使用。

4. 需要动态改变行为

当一个对象的行为在运行时可能会发生变化时,策略模式可以帮助你在对象的生命周期内动态改变其行为。例如:

  • 工作流引擎:在一个工作流系统中,工作流的处理方式可能会随着状态的变化而变化。可以使用策略模式来处理不同的工作流阶段。
  • 文本校验:在用户输入验证的系统中,可以根据不同的输入类型或验证规则(如电子邮件验证、电话号码验证、用户名验证等)动态选择不同的校验策略。

5. 需要增强可维护性和扩展性

当系统需要经常添加新的策略或修改现有策略时,策略模式提供了一种优雅的方式来增强系统的可维护性和扩展性。例如:

  • 插件系统:在一个插件系统中,可以使用策略模式来管理不同的插件功能,每个插件都可以作为一个策略来实现。
  • 报表生成:在报表生成系统中,可以使用策略模式来支持不同类型的报表格式(如 PDF、Excel、CSV 等),便于未来添加新的报表格式。

四、总结

        策略模式中,每一种算法都被单独的封装成一个策略,客户端通过上下文(Context)平滑地切换不同的算法类。简单来说策略模式就好比向客户提供多种可选方案,让客户自主选择需要执行哪种方案(具体算法类);他的优点也是其缺点,如果客户想根据自身的实际情况选择哪种方案,就必须了解提供的所有可选方案(算法类)的区别。意味着客户需具有统筹全局和精湛专业的能力,以便适时选择恰当的方案(算法类)。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【FreeRTOS】EventGroup事件标志组
  • spark集群搭建
  • wpf datagrid通过点击单元格 获取行列索引2.0
  • 适用于 Visual Studio 的 C++ 万能头
  • 密码生成器(HTML+CSS+JavaScript)
  • Java MR Map Reduce 模型
  • 综合能源充电站有序充电策略
  • 【数据集】遥感影像建筑物变化检测对比实验常用数据集分享
  • 基于Thymeleaf、bootstrap、layUI 混合前端应用
  • 为什么帕金森病患者的症状有时会出现波动性?
  • Godot《躲避小兵》实战之为游戏添加音效
  • 【IoTDB 线上小课 06】列式写入=时序数据写入性能“利器”?
  • 智能ai写作哪个好用?这几款工具让你的写作更加高效
  • .NET 给NuGet包添加Readme
  • 个性化营销:数字化时代的致胜法宝
  • “大数据应用场景”之隔壁老王(连载四)
  • 2018以太坊智能合约编程语言solidity的最佳IDEs
  • iOS小技巧之UIImagePickerController实现头像选择
  • k8s 面向应用开发者的基础命令
  • Meteor的表单提交:Form
  • Mithril.js 入门介绍
  • oldjun 检测网站的经验
  • Redux系列x:源码分析
  • spring-boot List转Page
  • spring学习第二天
  • Vue 重置组件到初始状态
  • Vue2 SSR 的优化之旅
  • 纯 javascript 半自动式下滑一定高度,导航栏固定
  • 得到一个数组中任意X个元素的所有组合 即C(n,m)
  • 快速构建spring-cloud+sleuth+rabbit+ zipkin+es+kibana+grafana日志跟踪平台
  • 理清楚Vue的结构
  • 前端技术周刊 2019-02-11 Serverless
  • 收藏好这篇,别再只说“数据劫持”了
  • 为什么要用IPython/Jupyter?
  • 2017年360最后一道编程题
  • ​数据结构之初始二叉树(3)
  • (pojstep1.1.1)poj 1298(直叙式模拟)
  • (二)PySpark3:SparkSQL编程
  • (附源码)springboot教学评价 毕业设计 641310
  • (机器学习-深度学习快速入门)第一章第一节:Python环境和数据分析
  • (每日一问)计算机网络:浏览器输入一个地址到跳出网页这个过程中发生了哪些事情?(废话少说版)
  • (小白学Java)Java简介和基本配置
  • (一) storm的集群安装与配置
  • (原创)Stanford Machine Learning (by Andrew NG) --- (week 9) Anomaly DetectionRecommender Systems...
  • (转)创业家杂志:UCWEB天使第一步
  • ***linux下安装xampp,XAMPP目录结构(阿里云安装xampp)
  • .NET C#版本和.NET版本以及VS版本的对应关系
  • .net 无限分类
  • .Net(C#)自定义WinForm控件之小结篇
  • .net访问oracle数据库性能问题
  • @autowired注解作用_Spring Boot进阶教程——注解大全(建议收藏!)
  • @SuppressWarnings(unchecked)代码的作用
  • @TableId注解详细介绍 mybaits 实体类主键注解
  • @Transactional事务注解内含乾坤?
  • [ 网络基础篇 ] MAP 迈普交换机常用命令详解