策略模式(大话设计模式)C/C++版本

策略模式

在这里插入图片描述
商场收银软件
根据客户所购买商品的单价和数量来收费

需求分析:

1. 输入单价+数量 => 界面逻辑
2. 计算(可能打折或者促销) => 业务逻辑
3. 输出结果 => 界面逻辑

感觉和计算器的逻辑流程差不多,可以用简单工厂模式实现吗?

可以但是不推荐
1. 简单工厂更多的语义是对象的创建问题
2. 而这里所谓的打折或促销的变化,更多的是算法(业务流程)的变化

策略模式较于简单工程模式

  1. 策略模式和简单工厂模式的UML区别:关联和聚合的区别
    而区别在代码上的体现就是:
    简单工厂模式侧重创建,接口语义设计更多的是create,返回的也就是对象
    策略模式侧重算法切换,接口语义设计更多的是传参使用参数对象的算法,返回的也就是策略
  2. 针对不同的促销手段类的扩展
    如果使用简单工厂类,则需要增加新的类后,还要修改工厂类;而策略模式是不需要的。
    策略模式只需要将促销手段类作为属性保存,然后在客户端调用,是可以被context类共享的。

策略模式深度分析:

  1. Strategy类在策略模式中的定位主要是封装算法或行为。
    它的设计重点在于提供一套清晰的接口,使得算法的实现可以被外部的Context对象调用,而不需要关心具体的实现细节。
    Strategy类的实例通常不包含任何唯一标识属性,因为它们的主要职责是执行特定的算法逻辑,而非存储数据或状态。
  2. 在策略模式中,Strategy类就像是一个工具箱中的工具,每个工具(Strategy实例)都有其特定的功能。
    Context对象就像是使用者,它可以根据当前的需求从工具箱中选择合适的工具(Strategy实例)来完成特定的任务。
    这种设计允许Context对象在运行时灵活地更换所使用的工具,而不需要修改自身的代码。
  3. Strategy类在策略模式中扮演的是算法提供者的角色,它通过清晰的接口对外提供服务,而内部的具体实现细节对外部使用者是透明的。
    这种设计模式鼓励将行为的定义和行为的使用分离,从而促进代码的模块化和可维护性。

C++

REF:https://www.cnblogs.com/Galesaur-wcy/p/15893407.html

#include <algorithm>
#include <iostream>
using namespace std;
#define free_ptr(p) \
    if (p)          \
        delete p;   \
    p = nullptr;

// Strategt类,定义所有支持的算法的公共接口
class Strategy
{
public:
    virtual ~Strategy(){};
    virtual void AlgorithmInterface() = 0;
};

// ConcreteStrategy 封装了具体的算法或行为,继承Strategy
class ConcreteStrategyA : public Strategy
{
    void AlgorithmInterface()
    {
        cout << "算法A实现" << endl;
    }
};

class ConcreteStrategyB : public Strategy
{
    void AlgorithmInterface()
    {
        cout << "算法B实现" << endl;
    }
};

class ConcreteStrategyC : public Strategy
{
    void AlgorithmInterface()
    {
        cout << "算法C实现" << endl;
    }
};

// Context,用一个ConcreteStrategy来配置,维护一个对Strategy的引用
class Context
{
public:
    Context(Strategy *strategy) : m_strategy(strategy){};
    ~Context() { free_ptr(m_strategy); }
    void AlgorithmInterface()
    {
        m_strategy->AlgorithmInterface();
    };

private:
    Strategy *m_strategy;
};

int main()
{
    Context *ContextA = new Context(new ConcreteStrategyA());
    Context *ContextB = new Context(new ConcreteStrategyB());
    Context *ContextC = new Context(new ConcreteStrategyC());

    ContextA->AlgorithmInterface();
    ContextB->AlgorithmInterface();
    ContextC->AlgorithmInterface();

    free_ptr(ContextA);
    free_ptr(ContextB);
    free_ptr(ContextC);
    return 0;
}

C

#include <stdio.h>

// 定义策略函数指针类型
typedef void (*StrategyFunc)(void);

// 定义策略结构体
typedef struct
{
    StrategyFunc strategyActioin;
} Strategy;

// 实现具体的策略A
void StrategyA()
{
    printf("算法A实现\n");
}

// 实现具体的策略B
void StrategyB()
{
    printf("算法B实现\n");
}

// 实现具体的策略C
void StrategyC()
{
    printf("算法C实现\n");
}

// 定义上下文结构体,用于封装策略
typedef struct
{
    Strategy strategy;
} Context;

// 创建上下文并设置策略
Context createContext(StrategyFunc strategy)
{
    Context context;
    context.strategy.strategyActioin = strategy;
    return context;
}

int main()
{
    // 创建不同的上下文,每个上下文使用不同的策略
    Context contextA = createContext(StrategyA);
    Context contextB = createContext(StrategyB);
    Context contextC = createContext(StrategyC);

    // 执行不同的策略
    contextA.strategy.strategyActioin();
    contextB.strategy.strategyActioin();
    contextC.strategy.strategyActioin();

    return 0;
}

思考

上述代码,其实省略了界面逻辑,也就是给用户选择策略的界面。当加上后你会发现,类型判断的业务逻辑是可以封装起来的。而且可以直接封装到Context类中,如下:

// Context,用一个ConcreteStrategy来配置,维护一个对Strategy的引用
class Context
{
public:
    Context(Strategy *strategy) : m_strategy(strategy) {}
    ~Context() { free_ptr(m_strategy); }
    Context(int opt)
    {
        switch (opt)
        {
        case 'A':
            m_strategy = new ConcreteStrategyA();
            break;
        case 'B':
            m_strategy = new ConcreteStrategyB();
            break;
        case 'C':
            m_strategy = new ConcreteStrategyC();
            break;
        default:
            m_strategy = nullptr;
            throw "Error input operator!";
            break;
        }
    }

    void AlgorithmInterface()
    {
        m_strategy->AlgorithmInterface();
    };

private:
    Strategy *m_strategy;
};

int main()
{
    Context *ContextInput = nullptr;
    cout << "请选择算法:" << endl;
    char Strategy;
    cin >> Strategy;
    try
    {
        ContextInput = new Context(Strategy);
        ContextInput->AlgorithmInterface();
    }
    catch (const char *err)
    {
        cout << err << endl;
        exit(-1);
    }

    Context *ContextA = new Context(new ConcreteStrategyA());
    Context *ContextB = new Context(new ConcreteStrategyB());
    Context *ContextC = new Context(new ConcreteStrategyC());

    ContextA->AlgorithmInterface();
    ContextB->AlgorithmInterface();
    ContextC->AlgorithmInterface();

    free_ptr(ContextA);
    free_ptr(ContextB);
    free_ptr(ContextC);
    free_ptr(ContextInput);
    
    return 0;
}

这就是策略模式+简单工厂模式!
可以看出:不仅隔离了业务和界面逻辑。而且在原策略模式下,降低了耦合。体现在客户端代码中ContextInput = new Context(Strategy)只有一个class Context需要了解,之前是Context *ContextC = new Context(new ConcreteStrategyC())中的两个class,使得客户端只需要了解一个class context,符合最少知识原则。

相关推荐

  1. 大话设计模式策略模式

    2024-07-11 18:32:04       43 阅读
  2. 简单工厂模式(大话设计模式)C/C++版本

    2024-07-11 18:32:04       21 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-11 18:32:04       66 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-11 18:32:04       70 阅读
  3. 在Django里面运行非项目文件

    2024-07-11 18:32:04       57 阅读
  4. Python语言-面向对象

    2024-07-11 18:32:04       68 阅读

热门阅读

  1. 基于单目摄像头实现的AR多人脸捕捉效果展示

    2024-07-11 18:32:04       17 阅读
  2. git 基本使用

    2024-07-11 18:32:04       22 阅读
  3. 【智能制造-15】常见通讯协议

    2024-07-11 18:32:04       22 阅读
  4. 网络编程学习part1

    2024-07-11 18:32:04       22 阅读
  5. IQN、UUID和SCSI-ID

    2024-07-11 18:32:04       22 阅读
  6. git撤销push

    2024-07-11 18:32:04       22 阅读
  7. 解决Spring Boot中的国际化与本地化问题

    2024-07-11 18:32:04       19 阅读
  8. Mongodb索引使用限制

    2024-07-11 18:32:04       25 阅读
  9. 数据建设实践之大数据平台(七)

    2024-07-11 18:32:04       25 阅读
  10. git revert怎么使用?

    2024-07-11 18:32:04       24 阅读
  11. Webpack配置及工作流程

    2024-07-11 18:32:04       21 阅读
  12. 如何理解李彦宏说的“不要卷模型,要卷应用”

    2024-07-11 18:32:04       22 阅读