简介
所谓策略,是指一系列的操作。
比如古代打仗,可以直接双方对垒派兵厮打,也可以等到月明星稀偷营劫寨,还可以略施小计。这些都是策略。
又比如计算税费时,不同国家的计算方法是不同的。如美国的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;
此时,使用了策略模式,就可以在灵活地决定使用何种算法。
增加一个新的算法时,也只需要少量的更改即可达到目的。