天天看點

設計模式-政策模式

政策模式(Strategy): 

    他定義了算法家族,分别封裝起來,讓它們之間可以互相替換,此模式讓算法的變化,不會影響到使用算法的客戶。

設計模式-政策模式

1.政策模式是一種定義一系列算法的方法,從概念上來看,所有這些算法完成的都是相同的工作,隻是實作不同,它可以以相同的方式調用所有的算法,減少各種算法類與使用算法類之間的耦合。

2.政策模式的Strategy類層次為Contex定義了一系列的可供重用的算法或行為。繼承有助于吸取出這些算法中的公共功能。

3.政策模式的優點是簡化了單元測試,因為每個算法都有自己的類,可以通過自己的接口單獨測試。

4.當不同的行為堆砌在一個類中時,就很難避免使用個條件語句來選擇合适的行為。将這些行為封裝在一個個獨立的Strtegy類中,可以在使用這些行為的類中消除條件語句。

5.政策模式就是用來封裝算法的,但在實踐中,我們發現可以用它來封裝幾乎任何類型的規則,隻要在分析過程中聽到需要在不同時間應用不同的業務規則,就可以考慮使用政策模式處理這種變化的可能性。

6.但是在基本的政策模式中,選擇所用具體實作的職責由用戶端對象承擔,并轉給政策模式的Context對象。這本身沒有接觸用戶端需要選擇判斷的壓力,而政策模式與簡單工廠模式結合後,選擇具體實作的職責也可以由Context來承擔,這就最大優化地減輕了用戶端的職責,然後在用反射優化一下工廠。

7.然後我實作一下加減乘除的基本政策模式和用簡單工廠優化的政策模式,至于反射優化簡單工廠就先不寫了,用的C++寫的,原因你們懂的。

基本政策模式實作加減乘除:

設計模式-政策模式
實作代碼:

#pragma once

class CInterface 
{
public:
	virtual bool GetValue(const int &nNumberA ,const int &nNumberB ,int &nAns) = 0;
};

class CAddition : public CInterface
{
public:
	bool GetValue(const int &nNumberA ,const int &nNumberB ,int &nAns)
	{
		nAns = nNumberA + nNumberB;
		return true;
	}
};

class CSubtraction : public CInterface
{
public:
	bool GetValue(const int &nNumberA ,const int &nNumberB ,int &nAns)
	{
		nAns = nNumberA - nNumberB;
		return true;
	}
};

class CMultiplication : public CInterface
{
public:
	bool GetValue(const int &nNumberA ,const int &nNumberB ,int &nAns)
	{
		nAns = nNumberA * nNumberB;
		return true;
	}
};

class CDivision : public CInterface
{
public:
	bool GetValue(const int &nNumberA ,const int &nNumberB ,int &nAns)
	{
		if(nNumberB == 0) 
			return false;
		nAns = nNumberA / nNumberB;
		return true;
	}
};

class CStrategy
{
private:
	CInterface *m_pAlgorithm;
public:
	void SetStrategy(CInterface *pAlgorithm)
	{
		m_pAlgorithm = pAlgorithm;
	}
	bool RunFun(const int &nNumberA ,const int &nNumberB ,int &Ans)
	{
		return m_pAlgorithm -> GetValue(nNumberA ,nNumberB ,Ans);
	}
};
           

用戶端調用:

#include "stdafx.h"
#include "StrategyMode.h"
#include <iostream>
#include <windows.h>
using namespace std;

int main()
{
	CStrategy *pStrate = new CStrategy();
	CInterface * pMarkMemAlgorithmBody[10] = {0};
	int nAlgId = 0 ,nAns;
	pMarkMemAlgorithmBody[nAlgId++] = new CAddition();
	pMarkMemAlgorithmBody[nAlgId++] = new CSubtraction();
	pMarkMemAlgorithmBody[nAlgId++] = new CMultiplication();
	pMarkMemAlgorithmBody[nAlgId++] = new CDivision();
	
	for(int i = 0 ;i < nAlgId ;i ++)
	{
		pStrate->SetStrategy(pMarkMemAlgorithmBody[i]);
		if(pStrate->RunFun(1 ,5 ,nAns))
		{
			cout<<nAns<<endl;
		}
		else 
		{
			cout<<"Error"<<endl;
		}
	}
    delete pStrate;
	for(int i = 0 ;i < nAlgId ;i ++)
	{
		delete pMarkMemAlgorithmBody[i];
	}
	return 0;
}
           

結果:

設計模式-政策模式

    然後是用簡單工廠來優化用戶端選擇的算法的問題,為此解決掉用戶端和算法實作之間本身的耦合度過高問題。大體思路就是我們直接在政策類裡面建造一個小的工廠,然後用戶端隻要建立政策類然後直接傳進去一個key值就行了。和工廠相比,這個姿勢并不是得到對象,而是設定對象,用戶端方面不會得到任何新的對象,隻是在設定政策裡面的一個算法變量指針的值而已,然後直接調用政策提供的函數,進而執行想要的結果,耦合度遠遠低于工廠模式(工廠模式用戶端不光知道工廠,起碼還要知道算法接口類型,不然怎麼建立出來一個類型變量來接受工廠建立出來的對象呢?)

結構實作代碼:

#pragma once
#include <string.h>

class CInterface 
{
public:
	virtual bool GetValue(const int &nNumberA ,const int &nNumberB ,int &nAns) = 0;
};

class CAddition : public CInterface
{
public:
	bool GetValue(const int &nNumberA ,const int &nNumberB ,int &nAns)
	{
		nAns = nNumberA + nNumberB;
		return true;
	}
};

class CSubtraction : public CInterface
{
public:
	bool GetValue(const int &nNumberA ,const int &nNumberB ,int &nAns)
	{
		nAns = nNumberA - nNumberB;
		return true;
	}
};

class CMultiplication : public CInterface
{
public:
	bool GetValue(const int &nNumberA ,const int &nNumberB ,int &nAns)
	{
		nAns = nNumberA * nNumberB;
		return true;
	}
};

class CDivision : public CInterface
{
public:
	bool GetValue(const int &nNumberA ,const int &nNumberB ,int &nAns)
	{
		if(nNumberB == 0) 
			return false;
		nAns = nNumberA / nNumberB;
		return true;
	}
};

class CStrategy
{
private:
	CInterface *m_pAlgorithm;
	CInterface * pMarkMemAlgorithmBody[10];
	int nAlgId;
public:
	CStrategy()
	{
		nAlgId = 0x00;
		memset(pMarkMemAlgorithmBody ,0x00 ,sizeof(pMarkMemAlgorithmBody));
	}
	void SetStrategy(int nKey)
	{
		m_pAlgorithm = NULL;
		switch (nKey)
		{
		case '+' :
			{
				m_pAlgorithm = new CAddition();
			}break;
		case '-' :
			{
				m_pAlgorithm = new CSubtraction();
			}break;
		case '*' :
			{
				m_pAlgorithm = new CMultiplication();
			}break;
		case '/' :
			{
				m_pAlgorithm = new CDivision();
			}break;
		default :break;
		}
		pMarkMemAlgorithmBody[nAlgId++] = m_pAlgorithm;
	}

	//釋放記憶體防止記憶體洩露
	~CStrategy()
	{
		for(int i = 0 ;i < nAlgId ;i ++)
		{
			delete pMarkMemAlgorithmBody[i];
		}
	}

	bool RunFun(const int &nNumberA ,const int &nNumberB ,int &Ans)
	{
		if(m_pAlgorithm != NULL)
		{
			return m_pAlgorithm -> GetValue(nNumberA ,nNumberB ,Ans);
		}
		else return -1;
	}
};           
#include "stdafx.h"
#include "StrategyMode.h"
#include <iostream>
#include <windows.h>
using namespace std;

int main()
{
	CStrategy *pStrate = new CStrategy();
	int nKey[] = {'+' ,'-' ,'*' ,'/'} ,nAns;
	for(int i = 0 ;i < 4 ;i ++)
	{
		pStrate->SetStrategy(nKey[i]);
		if(pStrate->RunFun(1 ,5 ,nAns))
		{
			cout<<nAns<<endl;
		}
		else 
		{
	        cout<<"Error"<<endl;
		}
	}
	delete pStrate;
	return 0;
}           

執行結果: