设计模式 策略(Strategy)模式

来源:互联网 发布:java并发编程艺术 编辑:程序博客网 时间:2024/06/14 18:09

一、定义

关于策略模式的定义,设计模式书中肯定都有,我就直接引用了:

策略模式定义了算法蔟,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户 –摘自《Head First 设计模式》

听起来很抽象有没有,别急,如果你没有接触过这种模式,光看定义脑海中就能构建出框架,那可真是太牛了,反正我第一次看到这个定义是一脸的懵逼。不过没关系,当学习完了这个模式后,再重新来读这个定义,我相信你会有很多收获,而且思路能飘得很远。

二、需求

接下来让我们来根据实际的需求来探讨一下这个模式:临近元旦,公司准备元旦前一天下班后,直接从公司出发一起到某五星级大酒店聚餐吃饭,公司领导在微信群里直接发了定位,并让你规划几条合适的路线,方便给员工分组让其结伴而去。

你接到通知后,快马加鞭,过程很辛苦,但最终不负嘱托,规划出了几条路线:

/** * 这是交通路线的接口 */public interface IStrategyTrafficRoutes {    //交通路线信息    void trafficRoutesInfo();}

为什么要使用接口,而不是直接使用具体的路线类?因为我们不应该把每个员工与具体的交通路线绑在一起,员工在出发前有权利改变路线(动态绑定),而当员工持有一个抽象交通路线类时,我们就可以在运行时动态的引用正确的具体交通路线类型(多态思想),所以我们应该针对接口编程,不针对实现编程。

第一种路线,步行最少,非常适合比较懒的员工

public class ShortestWalkRoutes implements IStrategyTrafficRoutes{    @Override    public void trafficRoutesInfo() {        //其实可以扩充出复杂的逻辑,但思路一样,所以就直接打印一句话得了        System.out.println("采用了步行距离最少的交通路线...分为1组");    }}

第二种路线换乘车辆最少,最适合不愿意多倒腾的员工了

public class TransferChangeLeastRoutes implements IStrategyTrafficRoutes {    @Override    public void trafficRoutesInfo() {        System.out.println("采用了换成车辆最少的路线...分为2组");    }}

第三种路线花费时间最少,非常适合时间观念很强的人了

public class TimeLeastRoutes implements IStrategyTrafficRoutes {    @Override    public void trafficRoutesInfo() {        System.out.println("采用了花费时间最少的路线...分为3组");    }}

第四种路线不拥挤,虽然时间长了点,但坐着比较舒心

public class MostComfortableRoutes implements IStrategyTrafficRoutes {    @Override    public void trafficRoutesInfo() {        System.out.println("采用了最舒服的路线...分为4组");    }}

交通路线的不同,这也是这个需求(下班打卡-路上-吃饭)每个员工变化的部分,我们之所以把每种具体路线都单独的封装起来,而不是写成一个个方法添加到员工类内部,是因为考虑到代码的复用,符合封装变化的OO原则

规划完了,应该让员工自己选择路线了吧

/** * 这是一个员工类的基类 * @author zmj */public abstract class StaffBase {    //员工的交通路线    IStrategyTrafficRoutes routes;    public void setRoutes(IStrategyTrafficRoutes routes){        this.routes = routes;    }    //针对接口编程,而不是具体实现,这样我们就不会把特定路线和特定员工死死的绑定在一起    public void showStaffRoutes(){        routes.trafficRoutesInfo();    }    //每个员工都有自己的名字(同样的还有员工号等等,我们只说思路)    public abstract void showName();}

在StaffBase类中加入接口类型变量(而不是具体的交通路线),每个员工都会动态的设置这个变量以在运行时引用正确的行为类型(例如:步行最少、换成最少等),所以我们应该针对接口编程,而非针对实现编程。

这是员工1号

public class StaffOne extends StaffBase {    public StaffOne(){        //员工1选择了步行最少的路线        //此处之所以没有直接new主要是不想让员工和路线绑的死死的        routes = RoutesFactory.getRoutes(1);    }    @Override    public void showName() {        System.out.print("本人张三:");    }}

这里采用静态工厂方法,让员工的代码与路线对象创建代码解耦

这是员工2号

public class StaffTwo extends StaffBase {    public StaffTwo() {        //员工2选择了换乘车辆最少        routes = RoutesFactory.getRoutes(2);    }    @Override    public void showName() {        System.out.print("本人李四:");    }}

这是员工3号

public class StaffThree extends StaffBase {    public StaffThree(){        //员工3选择了花费时间最少的路线        routes = RoutesFactory.getRoutes(3);    }    @Override    public void showName() {        System.out.print("本人王五:");    }}

同样的可以还有员工4号5号…n号,这里就不写了,不过,如果你写的话,你会发现扩充起来是相当容易,只需要添加新类并继承StaffBase基类即可,不需要更改其他代码,符合对扩展开放,对修改关闭原则。

/** * 这是一个简单的静态工厂,主要是产生一些路线的对象 * @author zmj * */public class RoutesFactory {    /**     * @param id 员工的编号     * @return 返回其填写的交通路线     */    public static IStrategyTrafficRoutes getRoutes(int id) {        IStrategyTrafficRoutes routes;        switch (id) {        case 1:            //步行最少            routes = new ShortestWalkRoutes();             break;        case 2:            //换乘车辆最少            routes = new TransferChangeLeastRoutes();             break;        case 3:            //花费时间最少            routes = new TimeLeastRoutes();             break;        case 4:            //最舒服的路线            routes = new MostComfortableRoutes();             break;        default:            //如果新来一个员工,还没有员工编号呢,那就选择时间最少吧,毕竟新人嘛,迟到可不好            routes = new TimeLeastRoutes();             break;        }        return routes;    }}

测试一下我们的这个设计吧

public class StrategyPatternTest {    public static void main(String[] args) {        //员工1号张三        StaffBase staff1 = new StaffOne();        //员工2号李四        StaffBase staff2 = new StaffTwo();        //员工3号王五        StaffBase staff3 = new StaffThree();        //员工1号选择了步行最少的交通方式        staff1.showName();        staff1.showStaffRoutes();        //员工2号选择了换乘车辆最少的交通方式        staff2.showName();        staff2.showStaffRoutes();        //员工3号选择了花费时间最少的交通方式        staff3.showName();        staff3.showStaffRoutes();        //由于今天时间充足,员工1号要求换成最舒服的路线        staff1.setRoutes(new MostComfortableRoutes());        staff1.showName();        staff1.showStaffRoutes();    }}

最终的运行结果

这里写图片描述

源码点击下载

阅读全文
0 0
原创粉丝点击