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

news2024/11/16 9:31:53

一、策略模式简介

策略模式(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)平滑地切换不同的算法类。简单来说策略模式就好比向客户提供多种可选方案,让客户自主选择需要执行哪种方案(具体算法类);他的优点也是其缺点,如果客户想根据自身的实际情况选择哪种方案,就必须了解提供的所有可选方案(算法类)的区别。意味着客户需具有统筹全局和精湛专业的能力,以便适时选择恰当的方案(算法类)。

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

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

相关文章

后端微服务架构:构建分布式博客系统

后端微服务架构&#xff1a;构建分布式博客系统 在当今的软件开发领域&#xff0c;微服务架构已经成为构建可扩展、灵活且易于维护的应用程序的主流选择。本文将探讨如何利用微服务架构来设计和实现一个分布式的博客系统。 1. 微服务架构简介 微服务架构是一种将应用程序分解…

练习题 期望dp

题目 分析&#xff1a; 首先注意到期望有线性性&#xff1a; E ( a b ) E ( a ) E ( b ) E(ab)E(a)E(b) E(ab)E(a)E(b)&#xff0c;其中 a a a、 b b b不要求相互独立。 因为网上很多地方的证明不严谨&#xff0c;所以这里证明一下&#xff1a; E ( a b ) ∑ i i ⋅ P …

C语言基础(十八)

1、共用体&#xff08;Union&#xff09;是一种特殊的数据类型&#xff0c;也被称为联合体&#xff0c;它允许在相同的内存位置存储不同的数据类型&#xff0c;每次只能存储其中一种类型的值。共用体是一种数据结构&#xff0c;多个不同类型的变量能够共享同一段内存空间。在C语…

OpenAI推出新功能:GPT-4o正式上线微调功能,限时免费!

GPT-4o正式上线微调功能&#xff0c;限时免费&#xff01; 每个组织每天可以免费获得多达100万个训练token&#xff0c;活动将持续到9月23日。 这意味着开发者们现在可以利用自定义数据集对GPT-4o进行微调&#xff0c;从而以较低的成本构建自己的应用程序。 据悉&#xff0c;G…

推荐3款在Windows系统上运行流畅、音质出众的音乐播放器

foobar2000 Foobar2000是一款由原Winamp开发公司的Peter Pawlowski开发的免费多功能音频播放器&#xff0c;具有高度定制化和丰富的功能。它支持多种音频格式&#xff0c;包括MP3、AAC、WMA、FLAC、WAV等&#xff0c;并且可以进行音频转码和格式转换。此外&#xff0c;Foobar20…

C盘满了,如何清理C盘

目录 磁盘清理删除休眠文件查看系统盘的存储占比卸载掉安装在系统盘的软件更改临时文件、文档等的存储位置 磁盘清理 选择自己的系统盘&#xff0c;我的是G盘。清理系统文件删除休眠文件 删除休眠文件 管理员打开cmd powercfg -h off 直接减少几个g的C盘占用 查看系统盘的存储…

世媒讯海外发稿:全球知名的中文媒体平台

新闻媒体网站专注于媒体行业中各类新闻的网站&#xff0c;也是网友最爱访问的网站类型之一。以下是一些知名的中文媒体平台&#xff0c;它们不仅提供华文内容&#xff0c;还具有较高的访问量和影响力。以下是十大可发布中文新闻稿的知名媒体&#xff0c;包括其月访问量、地区排…

【连续4届EI稳定检索】第五届计算机工程与智能控制学术会议(ICCEIC 2024,10月11-13)

第五届计算机工程与智能控制学术会议&#xff08;ICCEIC 2024&#xff09;将于2024年10月11日至13日在广州举办&#xff0c;聚焦计算机工程与智能控制前沿&#xff0c;涵盖网络安全、硬件系统、软件工程、嵌入式创新等多个核心议题及交叉学科研究。 ICCEIC 2024将计算机工程和智…

QT 程序直接崩溃The program has unexpectedly finished.

QT报错比较难处理&#xff0c;因为给出的控制台输出太宽泛甚至没有信息。 遇到当遇到这种直接崩溃的&#xff0c;试着把一些代码注释掉&#xff0c;慢慢试出出错的位置 。 这里有一种可能的原因是因为有些变量没有初始化&#xff0c;就直接使用。 如下图&#xff1a; 当我运…

【Java】/* 二叉树 - 底层实现*/

一、前序遍历 - 递归 /* 1. 前序遍历 - 递归 */public void preOrder(TreeNode root) {//1. 如果根节点为nullif (root null) {return;}//本意&#xff1a;打印树的根&#xff0c;左&#xff0c;右节点//2. 打印根节点的值System.out.print(root.val " ");//3. 如…

X86 PVE 下安装路由存储系统iStoreOS

简介 iStoreOS是一个比较易用的路由存储系统&#xff0c;它能让你获得更好的网络及 存储的体验。 系统本身开源免费&#xff0c;目前系统代码开源在&#xff1a;Github iStoreOS 下载固件 固件下载&#xff1a;https://fw.koolcenter.com/iStoreOS/x86_64/ istoreos-22.03.7…

数据结构——顺序表和单链表

数据结构 基本概念&#xff1a; 数据结构是一门研究如何有效组织数据&#xff0c;并提高数据处理效率的学科。通过研究各种数据内部的逻辑关系&#xff0c;使用某种特定的存储形式&#xff0c;并在此基础上对数据实施各种操作&#xff0c;这些工作被称为称为广义上的算法。 …

盈利47亿,快手的危机感却没消失

文丨郭梦仪 又是一年互联网大厂的半年报成绩单放榜时&#xff0c;一批主打下沉市场的公司也在从追求高增长&#xff0c;转向了高利润。 8月20日盘后&#xff0c;快手发布了“营利双增”的业绩报告&#xff0c;但显然营收增长远远低于利润的增长。 伴随着与抖音停战&#xff…

选择排序【详解】

本期介绍&#x1f356; 主要介绍&#xff1a;排序中的选择排序。 文章目录 1. 前言2. 选择排序3. 优化选择排序 1. 前言 相信只要接触过C语言的同学都或多或少了解排序问题&#xff0c;其中最基本&#xff0c;且最为人所熟知的排序是&#xff1a;选择排序。下面我会带着大家重新…

深入解读LLaMA-Factory

转自&#xff1a;老朱读AI 1、介绍 LLaMA-Factory是一个开源平台&#xff0c;旨在为研究人员和开发者提供便捷的大型语言模型微调环境。通过LLaMA-Factory&#xff0c;用户可以轻松地加载预训练模型&#xff0c;调整模型参数&#xff0c;并在特定数据集上进行训练&#xff0c…

【Python机器学习】NLP分词——利用分词器构建词汇表(六)——词汇表归一化

目录 大小写转换 词干还原 词形归并 使用场景 词汇表大小对NLP流水线的性能有很大的影响&#xff0c;有一种减少词汇表大小的方法是将词汇表归一化以便意义相似的词条归并成单个归一化的形式。这样做一方面可以减少需要再词汇表中保留的词条数&#xff0c;另一方面也会提高…

记录|Visual Studio中的Git上传下载使用

目录 前言一、前提准备Step1 仓库准备Step2. 本地仓库和远程仓库绑定当前效果展示 二、下载更新内容到本地仓库情形Step1. 下载 三、更新内容&#xff0c;上传文件到远程仓库情形Step1. 下载Step2. 上传当前效果展示 更新时间 前言 这部分是使用过程中的经验 一、前提准备 St…

【数模资料包】最新数模国赛word+latex模版|数模常用的算法python+matlab代码

【2024最全国赛研赛数模资料包】C君珍贵国一数模资料&#xff5c;最新数模国赛wordlatex模版&#xff5c;数模常用的算法pythonmatlab代码 国赛指&#xff1a;高教社杯全国大学生数学建模竞赛&#xff0c;研赛指&#xff1a;华为杯研究生数学建模竞赛。资料内容具体看文末卡片…

【C++算法/学习】位运算详解

✨ 忍能对面不相识&#xff0c;仰面欲语泪现流 &#x1f30f; &#x1f4c3;个人主页&#xff1a;island1314 &#x1f525;个人专栏&#xff1a;算法学习 &#x1f680; 欢迎关注&#xff1a;&#x1f44d;点赞 &…

【Python 千题 —— 基础篇】面积计算(多种图形面积计算)

Python 千题持续更新中 …… 脑图地址 &#x1f449;&#xff1a;⭐https://twilight-fanyi.gitee.io/mind-map/Python千题.html⭐ 题目描述 题目描述 编写一个面向对象的程序&#xff0c;定义一个基类 Shape 和两个派生类 Circle 和 Rectangle&#xff0c;用来计算不同图形…