一,策略模式
1.1,应用场景
做一个商场的收银软件,根据商品的价格以及优惠条件,计算出最终的价格,对应的代码如下:
// 折扣算法接口
class IStrategy
{
public:
virtual double getPrice(double price) = 0;
};
// 商品打8折
class ConcreteStrategyA : public IStrategy
{
double getPrice(double price)
{
return price * 0.8;
}
};
// 满300减100
class ConcreteStrategyB : public IStrategy
{
double getPrice(double price)
{
if(price >= 300)
{
return price - 100;
}
return price;
}
};
// 上下文
class Context
{
public:
// 初始化时传入具体的策略对象
Context(IStrategy *strategy) : m_strategy(strategy){}
// 根据具体的策略对象调用对应的方法
double contextInterface(int price)
{
return m_strategy->getPrice(price);
}
private:
IStrategy *m_strategy;
};
// 客户端代码
void main()
{
Context *context;
String str = "打8折";
switch(str)
{
case "打8折":
context = new Context(new ConcreteStrategyA());
break;
case "满300减100":
context = new Context(new ConcreteStrategyB());
break;
}
double resourcePrice = 100;
double finalPrice = context->contextInterface(resourcePrice);
}
下面对应的是结构框图:
1.2,使用简单工厂模式优化前面的代码
上面的代码存在的问题就是把判断使用哪一个具体算法的逻辑放在了客户端,使用简单工厂模式优化上面的代码,如下:
// 上下文
class Context
{
public:
Context(String type) : m_strategy(NULL)
{
switch(type)
{
case "打8折":
m_strategy = new ConcreteStrategyA;
break;
case "满300减100":
m_strategy = new ConcreteStrategyB;
break;
}
}
// 根据具体的策略对象调用对应的方法
double contextInterface(int price)
{
return m_strategy->getPrice(price);
}
private:
IStrategy *m_strategy;
};
// 客户端代码
void main()
{
String type = "打8折";
Context *context = new Context(type);
double resourcePrice = 100;
double finalPrice = context->contextInterface(resourcePrice);
}
1.3,策略模式解决的问题
策略模式定义了一个算法家族,分别封装起来,让它们之间可以互相的替换,此模式让算法的变化不会影响到使用算法的客户。策略模式的重点不是如何实现算法,而是如何组织、调用这些算法,从而让程序结构更灵活,具有更好的维护性和扩展性。策略模式一个很大的特点就是各个策略算法的平等性。对于一系列具体的策略算法,大家的地位是完全一样的,正因为这个平等性,才能实现算法之间可以相互替换。所有的策略算法在实现上也是相互独立的,相互之间是没有依赖的。所以可以这样描述这一系列策略算法:策略算法是相同行为的不同实现。
1.4,策略模式的优缺点
优点:
- 策略模式定义了一个算法家族,分别封装起来,不同的算法之间可以自由的切换。
- 此模式让算法的变化,不会影响到使用算法的客户,客户端使用固定的接口
context->contextInterface(resourcePrice)
使用不同的算法。 - 扩展性好,如果此时增加一个新的优惠策略,只用添加一个新的类实现
IStrategy
接口,并在Context
类中增加一条case分支语句就完成了。
缺点:
- 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。换言之,策略模式只适用于客户端知道算法或行为的情况。
- 由于策略模式把每个具体的策略实现都单独封装成为类,如果备选的策略很多的话,那么对象的数目就会很可观。