介绍
- 定义:定义算法家族,分别封装起来,让他们之间可以相互调用,此模式让算法的变化不会影响到使用算法的用户
- 说明:大量的if…else…结构,使用策略模式减少或者消除此结构。
- 适用场景
- 系统有很多类,而他们的区别仅仅在于他们的行为不同
- 一个系统需要动态地在几个算法中选择一个
- 优点
- 符合开闭原则
- 避免使用多重条件转移语句,例如 if…else or switch
- 提高算法的保密性,安全性
- 缺点
- 客户端必须知道所有的策略类,并自行决定使用哪一个策略
- 产生很多策略类
- 相关设计模式
- 策略模式和工厂模式
- 策略模式和状态模式
代码实现(简单版)
业务场景:最近天气总是变化,搞得小明一下穿毛衣(Sweater),一下穿短袖(Short),一下穿长袖(Long)。据此我们模拟此场景。
天气不停地变化,我们定义一个天气变化类WeatherChanged。根据天气变化的不同,我们采取不同的穿衣策略:穿毛衣(SweaterDressStrategy),穿短袖(ShortDressStrategy),穿长袖(LongDressStrategy)。
下面是具体的代码实现。
首先我们定义一个穿衣策略的接口类DressStrategy:
/**
* 穿衣服的接口策略类
*/
public interface DressStrategy {
void wear();
}
三种穿衣策略的具体接口实现:
/**
* 穿毛衣策略
*/
public class SweaterDressStrategy implements DressStrategy {
@Override
public void wear() {
System.out.println("穿毛衣");
}
}
/**
* 穿长袖策略
*/
public class LongDressStrategy implements DressStrategy {
@Override
public void wear() {
System.out.println("穿长袖");
}
}
/**
* 穿短袖策略
*/
public class ShortDressStrategy implements DressStrategy {
@Override
public void wear() {
System.out.println("穿短袖");
}
}
下面是天气变化类。这里我们的实现思路是:外部感知天气的变化,然后采取不同的策略。对应于下面的代码就是,客户端(上层)根据具体的情况传入具体的DressStrategy穿衣服策略。
/**
* 天气变化类
*/
public class WeatherChanged {
/**
* 成员变量,策略。反应天气变化后 该执行的穿衣策略
*/
private DressStrategy dressStrategy;
/**
* 构造函数
* @param dressStrategy 传入穿衣策略
*/
public WeatherChanged(DressStrategy dressStrategy) {
this.dressStrategy = dressStrategy;
}
/**
* 执行策略的相应动作
*/
public void onAction(){
this.dressStrategy.wear();
}
}
测试类(客户端,上层应用)的测试代码:
public class Test {
public static void main(String[] args) {
// 天气太热了,我要穿短袖
WeatherChanged weatherChanged0 = new WeatherChanged( new ShortDressStrategy() );
weatherChanged0.onAction();
// 天气比较凉快,我要穿长袖
WeatherChanged weatherChanged1 = new WeatherChanged( new LongDressStrategy() );
weatherChanged1.onAction();
// 天气太冷了,我要穿毛衣
WeatherChanged weatherChanged2 = new WeatherChanged( new SweaterDressStrategy() );
weatherChanged2.onAction();
//控制台输出结果:
/*
穿短袖
穿长袖
穿毛衣
*/
}
}
代码实现(结合工厂模式)
注意到上面的测试类中,每个策略都需要我们一个个通过new操作符来依次获取,比较麻烦。现在我们通过工厂类来获取特定的策略。
/**
* 天气变化,策略生成工厂
*/
public class WeatherChangedStrategyFactory {
public static final int WEATHER_CHANGED_MODE_COLD = -1; // 凉爽
public static final int WEATHER_CHANGED_MODE_HOT = 0; // 炎热
public static final int WEATHER_CHANGED_MODE_COLDER = 1; // 冬天
private static Map<Integer, DressStrategy> mp = new HashMap<>();
static {
mp.put( WEATHER_CHANGED_MODE_COLD, new LongDressStrategy() );
mp.put( WEATHER_CHANGED_MODE_HOT, new ShortDressStrategy() );
mp.put( WEATHER_CHANGED_MODE_COLDER, new SweaterDressStrategy() );
}
private WeatherChangedStrategyFactory(Integer WEATHER_CHANGED_MODE){
}
public static DressStrategy getStrategy(Integer WEATHER_CHANGED_MODE){
if( mp.containsKey( WEATHER_CHANGED_MODE ) )
return mp.get( WEATHER_CHANGED_MODE );
return null;
}
}
测试类很简单:
public class Test {
public static void main(String[] args) {
//Integer mode = WeatherChangedStrategyFactory.WEATHER_CHANGED_MODE_COLD;
Integer mode = WeatherChangedStrategyFactory.WEATHER_CHANGED_MODE_COLDER;
//Integer mode = WeatherChangedStrategyFactory.WEATHER_CHANGED_MODE_HOT;
DressStrategy dressStrategy = WeatherChangedStrategyFactory.getStrategy( mode );
dressStrategy.wear();
}
}