策略模式

想一个场景

再过一个月就是国庆节了,就算你是个不爱出门的主儿,这么长的假期肯定也有出行的安排吧。

为了愉快的度过这段假期,我们可以先准备几个度假方案,然后从中选择一个:

  1. 去找平时没机会见到的老朋友约饭约趴约电影
  2. 独自一人深度旅行
  3. 陪家人一起周边游 ...

不同的人根据自己的情况会选择不同的出行方案,

如果所有的情况都是已知的,而出行方案也是已知的,那么该如何选择呢?

应用到程序设计中,就需要一种设计模式了:策略模式

模式介绍

是的,如果你准备了好几种方案,然后只需要根据到时候的情况从中选择一种合适的方案的话,那就对了,这就是策略模式。

策略模式的组成很简单:执行类,抽象策略接口,具体策略类。

在国庆出游中,人对应执行类,出游计划对应抽象策略接口,独自旅行/陪家人旅行/等等对应具体策略类。

我们人,会先有一个出游计划的想法,然后再根据具体情况,从我们已知的出游方案中找到一个合适的具体的出游方案,而这就是策略模式。

类图

策略模式

应用

抽象策略接口,需在接口里定义所有的策略类型

/**
 * 旅游出行计划
 */
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);
    }
}

控制台输出

测试结果

结语

在使用策略模式的时候也有一些需要注意的地方:

  • 使用执行类的程序需要知道所有的具体策略类和它们所具备的能力,然后才能选择使用哪个具体策略,这样就不得不暴露具体策略类
  • 抽象策略类在定义传递参数的时候,要把所有具体策略类会用到的参数全部传递过去,这意味着参数的使用效率不高
  • 每添加一种具体策略类,都需要在执行类中对等添加
  • 会出现许多具体策略类

附属:额外的发现

还有一种设计模式叫做状态模式

这是一种很容易和策略模式搞混淆的模式。

相似的地方
  • 其角色组成相似:执行类,抽象状态接口,具体状态类
  • 都可以适应不同情况下的多种逻辑替换
不同的地方
  • 当程序中某个对象拥有多个状态,不同状态对应不同处理逻辑,这个状态在程序运行过程中会来回转换,则可以使用状态模式
  • 当程序中某个对象对某一行为有多种实现方式,各实现方式之间可以互相转换时,则使用策略模式。

转载于:https://my.oschina.net/u/3638962/blog/1528180

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值