簡介
所謂策略,是指一系列的操作。
比如古代打仗,可以直接雙方對壘派兵廝打,也可以等到月明星稀偷營劫寨,還可以略施小計。這些都是策略。
又比如計算稅費時,不同國家的計算方法是不同的。如美國的10%,日本的8%,歐萌的12%…等,這些也都是策略。
策略模式,就是把一個個的策略封裝起來,並且使它們可以相互替換。以達到算法獨立於客戶的目的。這樣可以在不改變客戶的情況下靈活地變更各種策略(算法)。
策略模式的目的就是爲了適應不同的需求,把這些容易變化的點(不同策略之間可能會互換)封裝起來。這樣就能夠在不變更原有代碼的情況下擴展需求。
本文以實現兩種不再的排序算法爲例實現策略模式。
不使用策略模式
首先看看不使用策略模式的方法。
現在需要設計一個升序排序算法:比較兩個數字,if a<b, return a。
class AsscendingSortAlgo
{
void swap(int &x, int &y)
{
int tmp = x;
x = y;
y = tmp;
}
bool comparisionLogic(int a, int b)
{
if(a > b)
return true;
else
return false;
}
public:
void sort(std::vector<int> &arr)
{
bool isSwapped = true;
int x = 0;
while (isSwapped)
{
isSwapped = false;
x++;
for (int i = 0; i < arr.size() - x; i++)
{
if (comparisionLogic(arr[i] , arr[i + 1]) )
{
swap(arr[i], arr[i + 1]);
isSwapped = true;
}
}
}
}
};
現在又增加了一個新需求:降序排序算法:比較兩個數字,if a<b, return b。
class DessendingSortAlgo
{
void swap(int &x, int &y)
{
int tmp = x;
x = y;
y = tmp;
}
bool comparisionLogic(int a, int b)
{
if(a < b)
return true;
else
return false;
}
public:
void sort(std::vector<int> & arr)
{
bool isSwapped = true;
int x = 0;
while (isSwapped)
{
isSwapped = false;
x++;
for (int i = 0; i < arr.size() - x; i++)
{
if (comparisionLogic(arr[i] , arr[i + 1]) )
{
swap(arr[i], arr[i + 1]);
isSwapped = true;
}
}
}
}
};
就是這樣,當算法與與策略緊密耦合時,一旦需求發生變化,就需要設計不同的新類。
這無疑會增加編碼和測試的難度,每次改動原有的代碼,哪怕只是一個字符,也需要對原有系統進行全面的測試。
如何解決這個問題?
策略模式
實現策略模式的步驟:
- 創建抽象策略接口定義行爲
- 從抽象策略接口繼承實現具體策略
- 創建算法類,在算法類內使用指針或引用與策略松耦合
- 運行時指定具體策略
開始實現我們的策略模式:
- 創建抽象策略接口
class IComparator
{
public:
virtual bool compare(int a, int b) = 0;
virtual ~IComparator(){}
};
- 創建具體策略
class LesserComprataor : public IComparator
{
public:
bool compare(int a, int b)
{
if(a > b)
return true;
else
return false;
}
};
class GreaterComprataor : public IComparator
{
public:
bool compare(int a, int b)
{
if(a < b)
return true;
else
return false;
}
};
- 創建算法類
class SortingAlgo
{
IComparator * m_pComparator;
void swap(int &x, int &y)
{
int tmp = x;
x = y;
y = tmp;
}
public:
SortingAlgo()
{
m_pComparator = new LesserComprataor();
}
void sort(std::vector<int> & arr, IComparator * pComparator = NULL)
{
if(pComparator == NULL)
pComparator = m_pComparator;
bool isSwapped = true;
int x = 0;
while (isSwapped)
{
isSwapped = false;
x++;
for (int i = 0; i < arr.size() - x; i++)
{
if (pComparator->compare(arr[i] , arr[i + 1]) )
{
swap(arr[i], arr[i + 1]);
isSwapped = true;
}
}
}
}
};
- 使用算法類,此時可以靈活地使用不同的策略
std::vector<int> arr = {1,5,2,4,3};
SortingAlgo obj;
IComparator * pComp = new LesserComprataor();
obj.sort(arr, pComp);
for (int var = 0; var < 5; ++var)
{
std::cout<<arr[var]<<" ";
}
std::cout<<std::endl;
delete pComp;
pComp = NULL;
pComp = new GreaterComprataor();
obj.sort(arr, pComp);
for (int var = 0; var < 5; ++var)
{
std::cout<<arr[var]<<" ";
}
std::cout<<std::endl;
delete pComp;
pComp = NULL;
obj.sort(arr);
for (int var = 0; var < 5; ++var)
{
std::cout<<arr[var]<<" ";
}
std::cout<<std::endl;
delete pComp;
pComp = NULL;
此時,使用了策略模式,就可以在靈活地決定使用何種算法。
增加一個新的算法時,也只需要少量的更改即可達到目的。