想一个场景
再过一个月就是国庆节了,就算你是个不爱出门的主儿,这么长的假期肯定也有出行的安排吧。
为了愉快的度过这段假期,我们可以先准备几个度假方案,然后从中选择一个:
- 去找平时没机会见到的老朋友约饭约趴约电影
- 独自一人深度旅行
- 陪家人一起周边游 ...
不同的人根据自己的情况会选择不同的出行方案,
如果所有的情况都是已知的,而出行方案也是已知的,那么该如何选择呢?
应用到程序设计中,就需要一种设计模式了:策略模式
模式介绍
是的,如果你准备了好几种方案,然后只需要根据到时候的情况从中选择一种合适的方案的话,那就对了,这就是策略模式。
策略模式的组成很简单:执行类,抽象策略接口,具体策略类。
在国庆出游中,人对应执行类,出游计划对应抽象策略接口,独自旅行/陪家人旅行/等等对应具体策略类。
我们人,会先有一个出游计划的想法,然后再根据具体情况,从我们已知的出游方案中找到一个合适的具体的出游方案,而这就是策略模式。
类图
应用
抽象策略接口,需在接口里定义所有的策略类型
/**
* 旅游出行计划
*/
public interface TravelStrategy {
//不出行
int TRAVEL_TYPE_NONE = 0;
//陪家人出行
int TRAVEL_TYPE_FAMILY = 1;
//独自出行
int TRAVEL_TYPE_ALONE = 2;
void travel(int holidayCount);
}
具体策略类:独自出行
public class TravelAloneStrategy implements TravelStrategy{
@Override
public void travel(int holidayCount) {
System.out.println("我有"+holidayCount+"天假期,我可以先去张家界踩玻璃桥,再去南昌喝瓦罐汤");
}
}
具体策略类:不出行
public class TravelNoneStrategy implements TravelStrategy{
@Override
public void travel(int holidayCount) {
System.out.println("我有"+holidayCount+"天假期,没有假期啊!呜呜呜~~");
}
}
具体策略类:陪家人出行
public class TravelWithFamilyStrategy implements TravelStrategy{
@Override
public void travel(int holidayCount) {
System.out.println("我有"+holidayCount+"天假期,我可以和家人一起去海南玩");
}
}
执行类:一个人和TA拥有的出行方案,出行方案可以拓展
public class Person {
private String name;
private Map<Integer,TravelStrategy> travelStrategyMap;
public Person(String name){
this.name = name;
init();
}
private void init(){
travelStrategyMap = new HashMap();
travelStrategyMap.put(TravelStrategy.TRAVEL_TYPE_FAMILY,new TravelWithFamilyStrategy());
travelStrategyMap.put(TravelStrategy.TRAVEL_TYPE_NONE,new TravelNoneStrategy());
travelStrategyMap.put(TravelStrategy.TRAVEL_TYPE_ALONE,new TravelAloneStrategy());
}
public void myTravelPlan(int myHolidayCount){
System.out.println("我是"+name);
int holidayType;
if(myHolidayCount>5){
holidayType = TravelStrategy.TRAVEL_TYPE_ALONE;
}else if (myHolidayCount<=0){
holidayType = TravelStrategy.TRAVEL_TYPE_NONE;
}else{
holidayType = TravelStrategy.TRAVEL_TYPE_FAMILY;
}
travelStrategyMap.get(holidayType).travel(myHolidayCount);
}
}
单元测试类
public class TravelStrategyTest {
@Test
public void test1(){
Person lily = new Person("lily");
Person juliet = new Person("Juliet");
Person leove = new Person("leove");
//莉莉有三天假期
lily.myTravelPlan(0);
//朱丽叶
juliet.myTravelPlan(3);
//leove
leove.myTravelPlan(7);
}
}
控制台输出
结语
在使用策略模式的时候也有一些需要注意的地方:
- 使用执行类的程序需要知道所有的具体策略类和它们所具备的能力,然后才能选择使用哪个具体策略,这样就不得不暴露具体策略类
- 抽象策略类在定义传递参数的时候,要把所有具体策略类会用到的参数全部传递过去,这意味着参数的使用效率不高
- 每添加一种具体策略类,都需要在执行类中对等添加
- 会出现许多具体策略类
附属:额外的发现
还有一种设计模式叫做状态模式
这是一种很容易和策略模式搞混淆的模式。
相似的地方
- 其角色组成相似:执行类,抽象状态接口,具体状态类
- 都可以适应不同情况下的多种逻辑替换
不同的地方
- 当程序中某个对象拥有多个状态,不同状态对应不同处理逻辑,这个状态在程序运行过程中会来回转换,则可以使用状态模式
- 当程序中某个对象对某一行为有多种实现方式,各实现方式之间可以互相转换时,则使用策略模式。