前言:对于设计模式基础概念可以去看[简说设计模式之设计模式概述]
一、什么是策略模式
策略(Strategy)模式的定义:该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。策略模式属于对象行为模式,它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。
举个例子:我们出门的时候会选择不同的出行方式,比如骑自行车、坐公交、坐火车、坐飞机、坐火箭等等,这些出行方式,每一种都是一个策略。再比如我们去逛商场,商场现在正在搞活动,有打折的、有满减的、有返利的等等,其实不管商场如何进行促销,说到底都是一些算法,这些算法本身只是一种策略,并且这些算法是随时都可能互相替换的,比如针对同一件商品,今天打八折、明天满100减30,这些策略间是可以互换的。
UML结构图如下:
其中,Context是上下文环境类,用一个具体ConcreteStrategy来配置,维护一个对Strategy对象的引用;Strategy是策略类,用于定义所有支持算法的公共接口;ConcreteStrategy是具体策略类,封装了具体的算法或行为,实现于Strategy。
1. Context上下文
Context上下文角色,也叫Context封装角色,起承上启下的作用,屏蔽高层模块对策略、算法的直接访问,封装可能存在的变化。
class Context
{
private Strategy strategy;
public Strategy getStrategy()
{
return strategy;
}
public void setStrategy(Strategy strategy)
{
this.strategy=strategy;
}
public void strategyMethod()
{
strategy.strategyMethod();
}
}
2. 策略角色
抽象策略角色,是对策略、算法家族的抽象,通常为接口,定义每个策略或算法必须具有的方法和属性。
interface Strategy
{
public void strategyMethod(); //策略方法
}
3. 具体策略角色
用于实现抽象策略中的操作,即实现具体的算法,下方用print代替。测试类共2个ConcreteStrategy,其它两个类与ConcreteStrategyA同理,就不再赘述了。
class ConcreteStrategyA implements Strategy
{
public void strategyMethod()
{
System.out.println("具体策略A的策略方法被访问!");
}
}
4.完整代码
package strategy;
public class StrategyPattern
{
public static void main(String[] args)
{
Context c=new Context();
Strategy s=new ConcreteStrategyA();
c.setStrategy(s);
c.strategyMethod();
System.out.println("-----------------");
s=new ConcreteStrategyB();
c.setStrategy(s);
c.strategyMethod();
}
}
//抽象策略类
interface Strategy
{
public void strategyMethod(); //策略方法
}
//具体策略类A
class ConcreteStrategyA implements Strategy
{
public void strategyMethod()
{
System.out.println("具体策略A的策略方法被访问!");
}
}
//具体策略类B
class ConcreteStrategyB implements Strategy
{
public void strategyMethod()
{
System.out.println("具体策略B的策略方法被访问!");
}
}
//环境类
class Context
{
private Strategy strategy;
public Strategy getStrategy()
{
return strategy;
}
public void setStrategy(Strategy strategy)
{
this.strategy=strategy;
}
public void strategyMethod()
{
strategy.strategyMethod();
}
}
二、策略模式的实现
用策略模式实现旅游的出行方式。
三、策略模式的应用
1. 何时使用
- 一个系统有许多类,而区分它们的只是他们直接的行为时
2. 方法
- 将这些算法封装成一个一个的类,任意的替换
3. 优点
- 算法可以自由切换
- 避免使用多重条件判断(如果不用策略模式我们可能会使用多重条件语句,不利于维护)
- 扩展性良好,增加一个策略只需实现接口即可
4. 缺点
- 策略类数量会增多,每个策略都是一个类,复用的可能性很小
- 所有的策略类都需要对外暴露
5. 使用场景
- 多个类只有算法或行为上稍有不同的场景
- 算法需要自由切换的场景
- 需要屏蔽算法规则的场景
6. 应用实例
- 出行方式,自行车、汽车等,每一种出行方式都是一个策略
- 商场促销方式,打折、满减等
7. 注意事项
- 如果一个系统的策略多于四个,就需要考虑使用混合模式来解决策略类膨胀的问题
四、策略模式的扩展
在一个使用策略模式的系统中,当存在的策略很多时,客户端管理所有策略算法将变得很复杂,如果在环境类中使用策略工厂模式来管理这些策略类将大大减少客户端的工作复杂度,其结构图 。