設計模式(六)策略模式C++

策略模式定義一系列的算法,把它們一個個封裝起來,並且使它們可相互替換。該模式使得算法可獨立於使用它的客戶而變化。
策略模式爲了適應不同的需求,只把變化點封裝了,這個變化點就是實現不同需求的算法,但是,用戶需要知道各種算法的具體情況。就像加班工資,不同的加班情況,有不同的算法。我們不能在程序中將計算工資的算法進行硬編碼,而是能自由的變化的。這就是策略模式。

角色:
    抽象策略角色(Strategy): 抽象策略類。
    具體策略角色(ConcreteStrategy):封裝了繼續相關的算法和行爲。
    環境角色(Context):持有一個策略類的引用,最終給客戶端調用。

下面是最直觀最簡單的策略模式

#include <iostream>
#include <windows.h>
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;

	system("pause");

	return 0;
}

在實際操作的過程中,我們會發現,在main函數中,也就是在客戶端使用策略模式時,會創建非常多的Strategy,而這樣就莫名的增加了客戶端的壓力,讓客戶端的複雜度陡然增加了。怎麼辦?可以把策略直接作爲參數傳遞給Context,但是Context內部要有對資源的釋放部分

更改之後如下

#include <iostream>
#include <windows.h>
#define  free_ptr(p) \
if(p) delete p; p = NULL;

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) : m_pStrategy(pStrategyArg)
	{
	}
	~Context()
	{
		free_ptr(m_pStrategy);
	}

	void ContextInterface()
	{
		m_pStrategy->AlgorithmInterface();
	}
private:
	Strategy *m_pStrategy;
};

int main()
{
	Context *pContextA = new Context(new ConcreteStrategyA);
	Context *pContextB = new Context(new ConcreteStrategyB);
	Context *pContextC = new Context(new ConcreteStrategyC);
	pContextA->ContextInterface();
	pContextB->ContextInterface();
	pContextC->ContextInterface();


	if (pContextA) delete pContextA;
	if (pContextB) delete pContextB;
	if (pContextC) delete pContextC;

	system("pause");

	return 0;
}

第三種實現方式是簡單工廠+策略模式,通過簡單工廠同樣能夠避免一次創建多個Strategy,代碼如下

#include <iostream>
#include <windows.h>
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;

	system("pause");
	return 0;
}

參考鏈接

參考鏈接2

發佈了195 篇原創文章 · 獲贊 41 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章