• [大话设计模式] 第2章: 策略模式


    策略模式(Strategy)

    定义一系列的算法,把每一个算法封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。根据不同的情况,创建不同的对象。对象不同类型相近,方法差别大, 尤其适合经常变动的多种不同算法。 一般用于多个类的方法名都相同,但是实现方式不同注重多个对象的相同行为:屏蔽方法名相同,算法实现细节不同之间的差异.

    • 面向对象中并非类越多越好,类的划分是为了封装,但分类的基础是抽象,具有相同属性和功能的对象的抽象集合才是类。
    • 策略模式:定义算法家族并分别封装,他们完成的工作相同,只是实现不同,可以互相替换。继承有助于析取这些算法的公共功能。此模式让算法的变化不会影响到使用算法的用户。
    • 策略与工厂模式结合,使客户端需要认识的类减少,耦合度更加降低。
    • 策略模式可以简化单元测试,因为每个算法可以通过自己的接口单独测试。
    • 只要在不同时间内应用不同的业务规则,就可以考虑用策略模式来处理这种变化的可能性。

    UML类图

    • Stragegy类 :定义所有支持的算法的公共接口
    • ConcreteStrategy :封装了具体的算法或行为,继承于Strategy
    • Context :用一个ConcreteStrategy来配置,维护一个对Strategy对象的引用或指针

    商场促销策略举例说明

    案例分析: 某商场有三种支付模式:

    1. 无优惠, 正常收取现金;
    2. 所有商品8折优惠;
    3. 每满300减100优惠;

    要求使用策略模式, 实现上述要求.
    注意: 也可以使用简单工厂模式, 简单工厂模式与策略模式的区别是: 简单工厂模式需要客户认识两个类, CashSuper和CashFactory, 而使用策略模式, 客户只需要认识一个类CashContext就可以了. 耦合性更加降低.
    UML类图如下

    代码如下:

    #include <stdio.h>
    
    typedef enum
    {
    	cashNormal, // 正常收费
    	cashRebate, // 打8折优惠
    	cashReturn, // 满300减100
    } CASHTYPE;
    
    // 抽象策略类
    class CashSuper
    {
    public:
    	virtual ~CashSuper(){ };
    	virtual double accept_cash(double money) = 0;
    };
    
    // 正常收费
    class CashNormal : public CashSuper
    {
    public:
    	CashNormal(){ };
    	double accept_cash(double money){
    		return money;
    	}
    };
    
    // 打8折优惠
    class CashRebate : public CashSuper
    {
    public:
    	CashRebate(double rebate_) : rebate(rebate_) { };
    	double accept_cash(double money){
    		return money * rebate;
    	}
    private:
    	double rebate;
    };
    
    // 满300减100
    class CashReturn : public CashSuper
    {
    public:
    	CashReturn(double con, double ret) : money_condition(con), money_return(ret){ };
    	double accept_cash(double money){
    		if(money > money_condition)
    			return money - (int)(money / money_condition) * money_return;
    		return money;
    	}
    private:
    	double money_condition;
    	double money_return;
    };
    
    class CashContext
    {
    public:
    	CashContext(CASHTYPE type);
    	~CashContext();
    	double get_result(double money);
    private:
    	CashSuper *c_super;
    };
    
    CashContext::CashContext(CASHTYPE type)
    {
    	switch(type) // 根据商场优惠类型不同, 创建不同对象, 类似简单工厂模式
    	{
    		case cashNormal:
    			c_super = new CashNormal();         break;
    		case cashRebate:
    			c_super = new CashRebate(0.8);      break;
    		case cashReturn:
    			c_super = new CashReturn(300, 100); break;
    		default:
    			c_super = NULL;
    	}
    }
    
    CashContext::~CashContext()
    {
    	delete c_super;
    }
    
    double CashContext::get_result(double money)
    {
    	return c_super->accept_cash(money);
    }
    
    int main()
    {
    	double pay = 600;
    	CashContext *cc = new CashContext(cashNormal); // 正常收费
    	printf("支付现金%f, 实际收现金 %f
    ", pay, cc->get_result(pay));
    
    	cc = new CashContext(cashRebate); // 8折
    	printf("支付现金%f, 实际收现金 %f
    ", pay, cc->get_result(pay));
    
    	cc = new CashContext(cashReturn); // 满300减100
    	printf("支付现金%f, 实际收现金 %f
    ", pay, cc->get_result(pay));
    
    	delete cc;
    
    	return 0;
    }
    
    /* 输出结果
    支付现金600.000000, 实际收现金 600.000000
    支付现金600.000000, 实际收现金 480.000000
    支付现金600.000000, 实际收现金 400.000000
    */
    

    参考链接

    大话设计模式C++源码: https://github.com/yogykwan/design-patterns-cpp

  • 相关阅读:
    搭建自己的博客(九):使用shell模式批量添加博客文章并增加分页功能
    搭建自己的博客(八):使用fontawesome框架来添加图标以及美化详情页
    linux系列(十):cat命令
    linux系列(九):touch命令
    搭建自己的博客(七):使用bootstrap框架美化导航栏
    linux系列(八):cp命令
    搭建自己的博客(六):添加首页,使用css对界面做美化
    linux系列(七):mv命令
    Re-enable extensions not coming from Chrome Web Store on Chrome v35+ (with enhanced security)
    liblensfun 在 mingw 上编译时遇到的奇怪问题
  • 原文地址:https://www.cnblogs.com/moon1992/p/7267574.html
Copyright © 2020-2023  润新知