我的相關博文
三種工廠模式詳解
策略模式
在GOF的《設計模式:可復用面向物件軟體的基礎》一書中對策略模式是這樣說的:
定義一系列的演算法,把它們一個個封裝起來,并且使它們可相互替換,該模式使得演算法可獨立于使用它的客戶而變化,
策略模式為了適應不同的需求,只把變化點封裝了,這個變化點就是實作不同需求的演算法,例如加班工資,不同的加班情況,有不同的計算加班工資的方法,
我們不能在程式中將計算工資的演算法進行硬編碼,而能夠自由變化,
這就是策略模式,


實驗1 策略模式+簡單工廠
代碼
#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(int x, int y) = 0;
virtual ~Strategy() = 0;
};
Strategy::~Strategy()
{}
class ConcreteStrategyA : public Strategy
{
public:
void AlgorithmInterface(int x, int y)
{
cout << "I am from ConcreteStrategyA: result=X+Y, = " << x+y << endl;
}
~ConcreteStrategyA(){
cout << "~ConcreteStrategyA()." << endl;
}
};
class ConcreteStrategyB : public Strategy
{
public:
void AlgorithmInterface(int x, int y)
{
cout << "I am from ConcreteStrategyB: result=X*Y, = " << x*y << endl;
}
~ConcreteStrategyB(){
cout << "~ConcreteStrategyB()." << endl;
}
};
class ConcreteStrategyC : public Strategy
{
public:
void AlgorithmInterface(int x, int y)
{
cout << "I am from ConcreteStrategyC: result=X-Y, = " << x-y << endl;
}
~ConcreteStrategyC(){
cout << "~ConcreteStrategyC()." << endl;
}
};
// 用戶類 : 使用演算法的用戶
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(int x, int y) // 定義一個介面來讓Stategy訪問用戶的資料
{
if (pStrategy)
pStrategy->AlgorithmInterface(x, y);
}
private:
Strategy *pStrategy; // 維護一個對Stategy物件的參考或指標
int a; // 私有資料,這是用戶資料,該用戶是獨立于演算法的用戶,用戶不需要了解演算法內部的資料結構
int b;
};
int main()
{
Context *pContext = new Context(StrategyA);
pContext->ContextInterface(100, 6);
if (pContext)
delete pContext;
}
上述的例子是策略模式,我們還能看到一點簡單工廠模式的影子,
百度到的絕大多數都是這種例子了, 這個代碼完美嗎?看下GoF的要領:

如果我們需要新增新的演算法,我們需要修改Context類的建構式,在里面新增新的演算法,這顯然不符合GoF采用擴展、子類化的精要,
所以引出了我下面的策略模式+抽象工廠的解決方案,
實驗2 策略模式+抽象工廠
代碼
#include <iostream>
using namespace std;
// The abstract strategy
class Strategy
{
public:
virtual void AlgorithmInterface(int x, int y) = 0;
virtual ~Strategy() = 0;
};
Strategy::~Strategy()
{}
class ConcreteStrategyA : public Strategy
{
public:
void AlgorithmInterface(int x, int y)
{
cout << "I am from ConcreteStrategyA: result=X+Y, = " << x+y << endl;
}
~ConcreteStrategyA(){
cout << "~ConcreteStrategyA().析夠" << endl;
}
};
class ConcreteStrategyB : public Strategy
{
public:
void AlgorithmInterface(int x, int y)
{
cout << "I am from ConcreteStrategyB: result=X*Y, = " << x*y << endl;
}
~ConcreteStrategyB(){
cout << "~ConcreteStrategyB().析夠" << endl;
}
};
class ConcreteStrategyC : public Strategy
{
public:
void AlgorithmInterface(int x, int y)
{
cout << "I am from ConcreteStrategyC: result=X-Y, = " << x-y << endl;
}
~ConcreteStrategyC(){
cout << "~ConcreteStrategyC().析夠" << endl;
}
};
// 用戶類 : 使用演算法的用戶
class Context
{
public:
Context(Strategy* paraStrategy)
{
pStrategy = paraStrategy;
}
~Context()
{
// 這里不需要析夠pStrategy, pStrategy對應物件的析夠會在delete pAbstractStrategyFactory時進行,
// 即,銷毀具體某個策略工廠物件時會負責析夠具體的策略物件,所以這里就不需要了,
}
void ContextInterface(int x, int y) // 定義一個介面來讓Stategy訪問用戶的資料
{
if (pStrategy)
pStrategy->AlgorithmInterface(x, y);
}
private:
Strategy *pStrategy; // 維護一個對Stategy物件的參考或指標
int a; // 私有資料,這是用戶資料,該用戶是獨立于演算法的用戶,用戶不需要了解演算法內部的資料結構
int b;
};
// 點評該類: 一條產品線下的產品,通常存在共性,
// 也就是說,維護一個對產品的抽象類通常是需要的,而不是必須的,
class AbstractStrategyFactory // 抽象工廠這里可以實作多個純虛方法
{
public:
virtual Strategy* createStrategy(string Strategy)=0;
virtual ~AbstractStrategyFactory(){}
};
class StrategyA_Factory:public AbstractStrategyFactory
{
Strategy *pStrategy;
public:
StrategyA_Factory():pStrategy(NULL)
{}
Strategy* createStrategy(string Strategy)
{
if(Strategy == "StrategyA"){
pStrategy = new ConcreteStrategyA();
return pStrategy;
}
return NULL;
}
~StrategyA_Factory()
{
cout << "~StrategyA_Factory(). 析夠" << endl;
if(pStrategy)
delete pStrategy;
}
};
class StrategyB_Factory:public AbstractStrategyFactory
{
Strategy *pStrategy;
public:
StrategyB_Factory():pStrategy(NULL)
{}
Strategy* createStrategy(string Strategy)
{
if(Strategy == "StrategyB"){
pStrategy = new ConcreteStrategyB();
return pStrategy;
}
return NULL;
}
~StrategyB_Factory()
{
if(pStrategy)
delete pStrategy;
}
};
class StrategyC_Factory:public AbstractStrategyFactory
{
Strategy *pStrategy;
public:
StrategyC_Factory():pStrategy(NULL)
{}
Strategy* createStrategy(string Strategy)
{
if(Strategy == "StrategyC"){
pStrategy = new ConcreteStrategyC();
return pStrategy;
}
return NULL;
}
~StrategyC_Factory()
{
if(pStrategy)
delete pStrategy;
}
};
int main(int argc, char *argv[])
{
AbstractStrategyFactory* pAbstractStrategyFactory; // 創建抽象工廠指標
pAbstractStrategyFactory = new StrategyA_Factory(); // 創建策略A的工廠
Strategy* pStrategy = pAbstractStrategyFactory->createStrategy("StrategyA"); //使用策略A工廠來生產出策略A
if(pStrategy == NULL)
{
cout << "pStrategy is NULL" << endl;
}
else
{
// 供用戶來使用策略A : 用戶使用策略A 和 策略A的實作,是松耦合的,
Context *pContext = new Context(pStrategy);
pContext->ContextInterface(100, 6);
delete pAbstractStrategyFactory;
if (pContext)
delete pContext;
}
return 0;
}
編譯運行:

此時,如果要新增演算法,那我覺得可以采用擴展、子類化的解決方案了,而不用像本博文上一個例子那樣,去修改已有的代碼了,
說大白話,如果要新增演算法,現在只需要在已有代碼基礎上去新增新演算法的相關代碼,而不是去修改已經寫好的一些函式的內部實作,
當然,這樣的設計會導致代碼量變大,所以一切都需要權衡,適合自己的就是最好的,
.
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/270953.html
標籤:其他
上一篇:醫惠集成平臺調研方案分析(二)
下一篇:分布式鎖的三種實作方式
