C++设计模式之策略模式

前言

刚刚加班回来;哎,公司规定平时加班只有10块钱的餐补;星期六和星期天加班,只给串休假;在国家规定的节假日按照3倍工资发放。那么对于这么多的计算加班费的方法,公司的OA系统是如何进行做的呢?这就要说到今天我这里总结的策略设计模式了。

策略模式

在GOF的《设计模式:可复用面向对象软件的基础》一书中对策略模式是这样说的:定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。该模式使得算法可独立于使用它的客户而变化。

策略模式为了适应不同的需求,只把变化点封装了,这个变化点就是实现不同需求的算法,但是,用户需要知道各种算法的具体情况。就像上面的加班工资,不同的加班情况,有不同的算法。我们不能在程序中将计算工资的算法进行硬编码,而是能自由的变化的。这就是策略模式。

UML类图

Strategy:定义所有支持的算法的公共接口。Context使用这个接口来调用某ConcreteStrategy定义的算法;
ConcreteStrategy:实现Strategy接口的具体算法;
Context:使用一个ConcreteStrategy对象来配置;维护一个对Stategy对象的引用,同时,可以定义一个接口来让Stategy访问它的数据。

使用场合

当存在以下情况时使用Strategy模式:

1.许多相关的类仅仅是行为有异。“策略”提供了一种用多个行为中的一个行为来配置一个类的方法;
2.需要使用一个算法的不同变体;
3.算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的、与算法相关的数据结构;
4.一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现。将相关的条件分支移入它们各自的Strategy类中以替代这些条件语句。(是不是和状态模式有点一样哦?)

代码实现

首先实现最单纯的策略模式,代码如下:

代码如下:

#include <iostream>
using namespace std;
 
// The abstract strategy
class Strategy
{
public:
     virtual void AlgorithmInterface() = 0;
};
 
class ConcreteStrategyA : public Strategy
{
public:
     void AlgorithmInterface()
     {
          cout<<"I am from ConcreteStrategyA."<<endl;
     }
};
 
class ConcreteStrategyB : public Strategy
{
public:
     void AlgorithmInterface()
     {
          cout<<"I am from ConcreteStrategyB."<<endl;
     }
};
 
class ConcreteStrategyC : public Strategy
{
public:
     void AlgorithmInterface()
     {
          cout<<"I am from ConcreteStrategyC."<<endl;
     }
};
 
class Context
{
public:
     Context(Strategy *pStrategyArg) : pStrategy(pStrategyArg)
     {
     }
     void ContextInterface()
     {
          pStrategy->AlgorithmInterface();
     }
private:
     Strategy *pStrategy;
};
 
int main()
{
     // Create the Strategy
     Strategy *pStrategyA = new ConcreteStrategyA;
     Strategy *pStrategyB = new ConcreteStrategyB;
     Strategy *pStrategyC = new ConcreteStrategyC;
     Context *pContextA = new Context(pStrategyA);
     Context *pContextB = new Context(pStrategyB);
     Context *pContextC = new Context(pStrategyC);
     pContextA->ContextInterface();
     pContextB->ContextInterface();
     pContextC->ContextInterface();
 
     if (pStrategyA) delete pStrategyA;
     if (pStrategyB) delete pStrategyB;
     if (pStrategyC) delete pStrategyC;
 
     if (pContextA) delete pContextA;
     if (pContextB) delete pContextB;
     if (pContextC) delete pContextC;
}

在实际操作的过程中,我们会发现,在main函数中,也就是在客户端使用策略模式时,会创建非常多的Strategy,而这样就莫名的增加了客户端的压力,让客户端的复杂度陡然增加了。那么,我们就可以借鉴简单工厂模式,使策略模式和简单工厂模式相结合,从而减轻客户端的压力,代码实现如下:

代码如下:

#include <iostream>
using namespace std;
 
// Define the strategy type
typedef enum StrategyType
{
    StrategyA,
    StrategyB,
    StrategyC
}STRATEGYTYPE;
 
// The abstract strategy
class Strategy
{
public:
    virtual void AlgorithmInterface() = 0;
    virtual ~Strategy() = 0; // 谢谢hellowei提出的bug,具体可以参见评论
};
 
Strategy::~Strategy()
{}
 
class ConcreteStrategyA : public Strategy
{
public:
    void AlgorithmInterface()
    {
        cout << "I am from ConcreteStrategyA." << endl;
    }
 
    ~ConcreteStrategyA(){}
};
 
class ConcreteStrategyB : public Strategy
{
public:
    void AlgorithmInterface()
    {
        cout << "I am from ConcreteStrategyB." << endl;
    }
 
    ~ConcreteStrategyB(){}
};
 
class ConcreteStrategyC : public Strategy
{
public:
    void AlgorithmInterface()
    {
        cout << "I am from ConcreteStrategyC." << endl;
    }
 
    ~ConcreteStrategyC(){}
};
 
class Context
{
public:
    Context(STRATEGYTYPE strategyType)
    {
        switch (strategyType)
        {
        case StrategyA:
            pStrategy = new ConcreteStrategyA;
            break;
 
        case StrategyB:
            pStrategy = new ConcreteStrategyB;
            break;
 
        case StrategyC:
            pStrategy = new ConcreteStrategyC;
            break;
 
        default:
            break;
        }
    }
 
    ~Context()
    {
        if (pStrategy) delete pStrategy;
    }
 
    void ContextInterface()
    {
        if (pStrategy)
            pStrategy->AlgorithmInterface();
    }
 
private:
    Strategy *pStrategy;
};
 
int main()
{
    Context *pContext = new Context(StrategyA);
    pContext->ContextInterface();
 
    if (pContext) delete pContext;
}

在上面这个代码中,其实,我们可能看到的更多的是简单工厂模式的应用,我们将策略模式将简单工厂模式结合在了一起,让客户端使用起来更轻松。

总结

策略模式和状态模式,是大同小异的;状态模式讲究的是状态的变化,和不同状态下,执行的不同行为;而策略模式侧重于同一个动作,实现该行为的算法的不同,不同的策略封装了不同的算法。策略模式适用于实现某一功能,而实现该功能的算法是经常改变的情况。在实际工作中,遇到了实际的场景,可能会有更深的体会。比如,我们做某一个系统,该系统可以适用于各种数据库,我们都知道,连接某一种数据库的方式是不一样的,也可以说,连接数据库的“算法”都是不一样的。这样,我们就可以使用策略模式来实现不同的连接数据库的策略,从而实现数据库的动态变换。

(0)

相关推荐

  • 详解C++设计模式编程中策略模式的优缺点及实现

    策略模式(Strategy):它定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.策略模式让算法的变化不会影响到使用算法的客户.策略模式和 Template 模式要解决的问题是相同(类似)的,都是为了给业务逻辑(算法)具体实现和抽象接口之间的解耦.策略模式将逻辑(算法)封装到一个类(Context)里面,通过组合的方式将具体算法的实现在组合对象中实现,再通过委托的方式将抽象接口的实现委托给组合对象实现.State 模式也有类似的功能,他们之间的区别将在讨论中给出. UML图

  • C++编程中使用设计模式中的policy策略模式的实例讲解

    在看<C++设计新思维>的时候,发现在一开始就大篇幅的介绍策略模式(policy),策略模式不属于经典设计模式中的一种,但是其实在我们日常的开发中是必不可少的.policy,策略,方针,这里的意思是指把复杂功能的类尽量的拆分为功能单一的简单类的组合,简单的类只负责单纯行为或结构的某一方面.增加程序库的弹性,可复用性,可扩展性.policy是一个虚拟的概念,他定义了某一类class的一些接口规范,并不与C++语法的关键字对应,只是一个抽象的概念. 实例1: //policy模式的常见使用实例sm

  • 深入理解C++之策略模式

    1  会飞的鸭子 Duck 基类,包含两个成员函数 (swim, display):派生类 MallardDuck,RedheadDuck 和 RubberDuck,各自重写继承自基类的 display 成员函数 class Duck { public: void swim(); virtual void display(); }; class MallardDuck : public Duck { public: void display(); // adding virtual is OK

  • 深入解析C++编程中对设计模式中的策略模式的运用

    策略模式也是一种非常常用的设计模式,而且也不复杂.下面我们就来看看这种模式. 定义:策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.策略模式让算法独立于使用它的客户而独立变化. 角色: 抽象策略角色(Strategy): 抽象策略类. 具体策略角色(ConcreteStrategy):封装了继续相关的算法和行为. 环境角色(Context):持有一个策略类的引用,最终给客户端调用. UML图: 例子: #include <iostream> using names

  • Java经典设计模式之策略模式原理与用法详解

    本文实例讲述了Java经典设计模式之策略模式.分享给大家供大家参考,具体如下: 策略模式指:策略模式指将程序中可变部分抽象分离成一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.策略模式让算法独立于使用它的客户而独立变化. 策略模式一般由下面三部分组成: 1. 抽象策略角色: 策略类,通常由一个接口或者抽象类实现. 2. 具体策略角色:包装了相关的算法和行为. 3. 环境角色:持有某一个策略类的引用,客户端调用. 策略模式设计原则: 1. 把程序中需要变化的部分抽离出来,独立于不变

  • Java设计模式之策略模式_动力节点Java学院整理

    定义:定义一组算法,将每个算法都封装起来,并且使他们之间可以互换. 类型:行为类模式 类图: 策略模式是对算法的封装,把一系列的算法分别封装到对应的类中,并且这些类实现相同的接口,相互之间可以替换.在前面说过的行为类模式中,有一种模式也是关注对算法的封装--模版方法模式,对照类图可以看到,策略模式与模版方法模式的区别仅仅是多了一个单独的封装类Context,它与模版方法模式的区别在于:在模版方法模式中,调用算法的主体在抽象的父类中,而在策略模式中,调用算法的主体则是封装到了封装类Context中

  • Android编程设计模式之策略模式详解

    本文实例讲述了Android编程设计模式之策略模式.分享给大家供大家参考,具体如下: 一.介绍 在软件开发中也常常遇到这样的情况:实现某一个功能可以有多种算法或者策略,我们根据实际情况选择不同的算法或者策略来完成该功能.例如,排序算法,可以使用插入排序.归并排序.冒泡排序等. 针对这种情况,一种常规的方法是将多种算法写在一个类中.例如,需要提供多种排序算法,可以将这些算法写到一个类中,每一个方法对应一个具体的排序算法:当然,也可以将这些排序算法封装在一个统一的方法中,通过if-else-或者ca

  • Java设计模式之策略模式原理与用法实例详解

    本文实例讲述了Java设计模式之策略模式原理与用法.分享给大家供大家参考,具体如下: 策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.策略模式让算法独立于使用它的客户而独立变化.其中JDK里面的TreeSet类和TreeMap类就用到了策略模式.这两个类是带排序的集合类,其中排序的规则就相当于策略模式里定义的一系列算法,而集合类就相当于是策略模式里的环境类,供用户使用,用只知道TreeSet和TreeMap是带排序的,至于怎么排序的,是由排序的算法决定的. 策略模式

  • Java设计模式之策略模式定义与用法详解

    本文实例讲述了Java策略模式定义与用法.分享给大家供大家参考,具体如下: 一. 定义: 定义一系列算法,把他们一个一个封装起来,并且使他们可以相互替换. 二. 优点: (1)上下文(Context)和具体策略(ConcreteStrategy)是松耦合关系,因此上下文只需要知道他要使用某一个实现  Strategy接口类的实例,但不需要知道是哪个类. (2)策略模式满足开闭原则,当增加新的具体类时,不需要修改上下文类的代码,上下文即可以引用新的具体策略的实例. 三. 实例: 下面就通过一个问题

  • php设计模式之策略模式应用案例详解

    本文实例讲述了php设计模式之策略模式应用.分享给大家供大家参考,具体如下: 策略模式 定义: 策略模式定义一系列的算法,将每个算法封装起来,并让它们可以相互装换.策略模式让算法独立于使用它的客户而独立变化. 角色分析: 抽象策略角色:策略类,通常由一个接口或者抽象类实现: 具体策略角色:包装了相关的算法和行为: 环境角色:持有一个策略类的引用,最终给客户端用. 应用场景: 多个类只区别在表现行为不同,可以使用策略模式,在运行的时动态选择具体要执行的行为. 需要在不同情况下使用不同的策略(算法)

  • PHP设计模式之策略模式原理与用法实例分析

    本文实例讲述了PHP设计模式之策略模式原理与用法.分享给大家供大家参考,具体如下: 策略模式(Strategy Pattern) 策略模式是对象的行为模式,用意是对一组算法的封装.动态的选择需要的算法并使用. 策略模式指的是程序中涉及决策控制的一种模式.策略模式功能非常强大,因为这个设计模式本身的核心思想就是面向对象编程的多形性思想. 策略模式的三个角色: 1. 抽象策略角色 2. 具体策略角色 3. 环境角色(对抽象策略角色的引用) 实现步骤: 1. 定义抽象角色类(定义好各个实现的共同抽象方

  • Python设计模式之策略模式实例详解

    本文实例讲述了Python设计模式之策略模式.分享给大家供大家参考,具体如下: 策略模式(Strategy Pattern):它定义了算法家族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化,不会影响到使用算法的客户. 下面是一个商场活动的实现 #!/usr/bin/env python # -*- coding:utf-8 -*- __author__ = 'Andy' ''' 大话设计模式 设计模式--策略模式 策略模式(strategy):它定义了算法家族,分别封装起来,让他们之

  • PHP设计模式之策略模式(Strategy)入门与应用案例详解

    本文实例讲述了PHP设计模式之策略模式(Strategy)入门与应用.分享给大家供大家参考,具体如下: 这个策略模式,意思就是定义一系列算法,把它们一个个封装起来,并且使它们可相互替换,使用得算法的变化可独立于使用它的客户,简单来讲就是,策略模式设计帮助构建的对象不必自身包含逻辑,而是能够根据需要利用其他对象中的算法. 来看下应用场景: 1. 多个类只区别在表现行为不同,可以使用Strategy模式,在运行时动态选择具体要执行的行为. 2. 需要在不同情况下使用不同的策略(算法),或者策略还可能

  • php设计模式之策略模式实例分析【星际争霸游戏案例】

    本文实例讲述了php设计模式之策略模式.分享给大家供大家参考,具体如下: 星际开地图对战,等5秒钟进入地图后,每个玩家都会拥有一个基地,几个农民等,还会有初始的人口供给.但这些是根据种族的不同而不同. 待解决的问题:我们需要根据种族的不同,而对玩家进行不同的初始化,最好将这些不同的处理方式封装. 思路:定义初始化的接口,然后制作不同种族的初始化类. 策略模式(Strategy)示例: 为了使代码不至于过长,一部分类的定义不在此写出,如果要调试,请用字符串等方式替代new. <?php //玩家的

随机推荐