【嵌入式c++】設計模式之策略模式(Strategy)

呆呆狗meng發表於2020-11-03

題目描述: 策略模式

動機(Motivation)

  • 在軟體構建過程中,某些物件使用的演算法可能多種多樣,經常改變,如果將這些演算法都編碼到物件中,將會使物件變得異常複雜;而且有時候支援不使用的演算法也是一個效能負擔。
  • 如何在執行時根據需要透明地更改物件的演算法?將演算法與物件本身解耦,從而避免上述問題?

模式定義

定義一系列演算法,把它們一個個封裝起來,並且使它們可互相替換(變化)。該模式使得演算法可獨立於使用它的客戶程式(穩定)而變化(擴充套件,子類化)。
——《設計模式》 GoF

要點總結

  • Strategy及其子類為元件提供了一系列可重用的演算法,從而可以使得型別在執行時方便地根據需要在各個演算法之間進行切換。
  • Strategy模式提供了用條件判斷語句以外的另一種選擇,消除條件判斷語句,就是在解耦合。含有許多條件判斷語句的程式碼通常都需要Strategy模式。
  • 如果Strategy物件沒有例項變數,那麼各個上下文可以共享同一個Strategy物件,從而節省物件開銷。

程式碼結構

.
├── build.sh
├── clearBuild.sh
├── CMakeLists.txt
├── src
│ ├── examStu.cpp
│ ├── include
│ │ └── examStu.h
│ └── main.cpp

原始碼例子1

examStu.h

#ifndef _EXANSTU__
#define _EXANSTU__

#include <iostream>
#include <string>
#include <vector>
using namespace std;



class Strategy
{
public:

//這裡有一個小知識 : 
/*
在某些類裡宣告純虛解構函式很方便。純虛擬函式將產生抽象類——不能例項化的類(即不能建立此型別的物件)。有些時候,你想使一個類成為抽象類,
但剛好又沒有任何純虛擬函式。怎麼辦?因為抽象類是準備被用做基類的,基類必須要有一個虛解構函式,純虛擬函式會產生抽象類,
所以方法很簡單:在想要成為抽象類的類裡宣告一個純虛解構函式。
這裡是一個例子:
class awov {
public:
  virtual ~awov() = 0;      // 宣告一個純虛解構函式
};
這個類有一個純虛擬函式,所以它是抽象的,而且它有一個虛解構函式,所以不會產生解構函式問題。但這裡還有一件事:必須提供純虛解構函式的定義:
awov::~awov() {}           // 純虛解構函式的定義
這個定義是必需的,因為虛解構函式工作的方式是:最底層的派生類的解構函式最先被呼叫,然後各個基類的解構函式被呼叫。
這就是說,即使是抽象類,編譯器也要產生對~awov的呼叫,所以要保證為它提供函式體。如果不這麼做,連結器就會檢測出來,最後還是得回去把它添上。
*/
    virtual ~Strategy()=0;  

    virtual void AlgorithmInterface() = 0;

};


class ConcreteStrategyA:public Strategy
{
public:
    ~ConcreteStrategyA(){};
    void AlgorithmInterface() override {cout << "from ConcreteStrategyA." << endl;}

};

class ConcreteStrategyB:public Strategy
{
public:
    ~ConcreteStrategyB(){};
    void AlgorithmInterface() override {cout << "from ConcreteStrategyB." << endl;}
    
};


class context
{
public:
    context(){};
    context(Strategy* pStrategy):pContextStrategy(pStrategy){}
    ~context(){};

    void ContextStrategy()
    {
        pContextStrategy->AlgorithmInterface();
    }
    Strategy * pContextStrategy;
    
private:

};

#endif

main.cpp

#include <iostream>
#include <string>
#include <memory>

#include "examStu.h"

using namespace std;


int main(int argc, char *argv[])
{
	Strategy* pA = new ConcreteStrategyA();
	Strategy* pB = new ConcreteStrategyB();

    context *pcontextA = new context(pA);
    pcontextA->pContextStrategy->AlgorithmInterface();   //這樣可以呼叫其他類中的函式

    context *pcontextB = new context(pB);
    pcontextB->ContextStrategy();

    delete pA;
    delete pB;  
    delete pcontextA;
    delete pcontextB;

 

    return 0;
}

原始碼例子2 (結合簡單模式)

程式碼結構

.
├── build.sh
├── clearBuild.sh
├── CMakeLists.txt
├── src 
│   ├── examStu.cpp
│   ├── include
│   │   └── examStu.h
│   └── main.cpp

examStu.h

#ifndef _EXANSTU__
#define _EXANSTU__

#include <iostream>
#include <string>
#include <vector>
using namespace std;


typedef enum _StrategyType
{
    CONCRETE_STRATAGY_BASE = 0,

    CONCRETE_STRATAGY_A = 1,
    CONCRETE_STRATAGY_B = 2,

    CONCRETE_STRATAGY_ERROR = -999,

}eStrategyType;


class Strategy
{
public:
    virtual ~Strategy()=0;  

    virtual void AlgorithmInterface() = 0;

};


class ConcreteStrategyA:public Strategy
{
public:
    ConcreteStrategyA(){}
    ~ConcreteStrategyA(){cout << "~ConcreteStrategyA()" << endl;};
    void AlgorithmInterface() override {cout << "from ConcreteStrategyA." << endl;}

};

class ConcreteStrategyB:public Strategy
{
public:
    ConcreteStrategyB(){}
    ~ConcreteStrategyB(){cout << "~ConcreteStrategyB()" << endl;};
    void AlgorithmInterface() override {cout << "from ConcreteStrategyB." << endl;}
    
};


class Context
{
public:
    Context(){};
    ~Context(){cout << "~Context()" << endl;}
    Context(eStrategyType  strategyType);

    void ContextStrategy();


private:
    std::shared_ptr<Strategy> pStrategy;

};

#endif

main.cpp

#include <iostream>
#include <string>
#include <memory>

#include "examStu.h"

using namespace std;


int main(int argc, char *argv[])
{
    Context *pcontextA = new Context(CONCRETE_STRATAGY_A);
    pcontextA->ContextStrategy();  

    Context *pcontextB = new Context(CONCRETE_STRATAGY_B);
    pcontextB->ContextStrategy();

    delete pcontextA;
    delete pcontextB;
    
    return 0;
}

相關文章