23种设计模式之策略模式

策略模式的定义:
策略模式定义了一系列的算法,并将每一个算法封装起来,而且使他们还可以相互替换,策略模式让算法独立于使用它的客户端而独立变化。
策略模式的使用场景:

  • 针对同一类型问题的多种处理方式,仅仅是具体行为有差别时
  • 需要安全地封装多种同一类型的操作时
  • 出现同一抽象类有多个子类,而又需要使用if-else或者 switch-case 来选择具体子类时

类图:
这里写图片描述

  • Context:用来操作策略的上下文环境
  • Stragety:策略的抽象
  • ConcreteStragegyA,ConcreteStragegyB,ConcreteStragegyC:具体的策略实现
    简单实现:
    通常如果一个问题有多个解决方案时,比较简单的方式就是利用if-else或者switch-case 方式来根据不同的场景选择不同的解决方案,OK,咱们以北京的公交车为例,参考《Android源码设计模式》,首先看下通常的编写方式
public class PriceCalculator {
    //公交车类型
    private static final int BUS = 1;
    //地铁类型
    private static final int SUBWAY = 2;

    public static void main(String[] args) {
        PriceCalculator calculator = new PriceCalculator();
        System.out.println("坐16公里的公交车票价位:" + calculator.calculatePrice(16, BUS));
    }

    /**
     * 北京公交车,十公里之内一元钱,超过十公里之后每加一元钱可以乘5公里
     *
     * @param km
     * @return
     */
    private int busPrice(int km) {
        //超过十公里的距离
        int extraTotal = km - 10;
        //超过的距离对5公里倍数
        int extraFactor = extraTotal / 5;
        //超过的距离对5公里取余
        int fraction = extraTotal % 5;
        //价格计算
        int price = 1 + extraFactor * 1;
        return fraction > 0 ? ++price : price;
    }

    /**
     * 6公里(含)内3元,6~12公里(含)4元,12~22公里(含)5元,22~32公里(含)6元
     *
     * @param km
     * @return
     */
    private int subwayPrice(int km) {
        if (km <= 6) {
            return 3;
        } else if (km < 12) {
            return 4;
        } else if (km < 22) {
            return 5;
        } else if (km < 32) {
            return 6;
        }
        return 7;
    }

    private int calculatePrice(int km, int type) {
        if (type == BUS) {
            return busPrice(km);
        } else if (type == SUBWAY) {
            return subwayPrice(km);
        }
        return 0;
    }
}

如果想增加一个选择,只能在else-if中添加

    private int calculatePrice(int km, int type) {
        if (type == BUS) {
            return busPrice(km);
        } else if (type == SUBWAY) {
            return subwayPrice(km);
        }else if(type == TAXT) {
            return taxiPrice(km);
        }
        return 0;
    }

很明显,PriceCalculator 类不是单一职责,1.计算公交车和地铁乘坐价格的职责。2.还有就是通过if-else的形式来判断使用哪种计算形式。当增加一种出行方式时,就需要增加一个方法。如上代码所示。整体代码比较混乱,这就是我们的主人公—策略模式登场的时候了。我们可以把每一种情景独立成一个函数,然后外部调用方法即可,但是这也是另一种耦合形式,对于可变性较大的算法族来说还是不太适合。
策略模式代码重构如下:

//计算接口
public interface CalculateStrategy {
    /**
     * 按距离来计算价格
     * @param km
     * @return
     */
    int calculatePrice(int km);
}

//公交车价格计算策略
public class BusStrategy implements CalculateStrategy {
    @Override
    public int calculatePrice(int km) {
        //超过十公里的距离
        int extraTotal = km - 10;
        //超过的距离对5公里倍数
        int extraFactor = extraTotal / 5;
        //超过的距离对5公里取余
        int fraction = extraTotal % 5;
        //价格计算
        int price = 1 + extraFactor * 1;
        return fraction > 0 ? ++price : price;
    }
}

//地铁价格计算策略
public class SubwayStrategy implements CalculateStrategy {
    @Override
    public int calculatePrice(int km) {
        if (km <= 6) {
            return 3;
        } else if (km < 12) {
            return 4;
        } else if (km < 22) {
            return 5;
        } else if (km < 32) {
            return 6;
        }
        return 7;
    }
}

我们再创建一个扮演角色Context角色的类

//公交出行价格计算器
public class TranficCalculator {
    public static void main(String[] args){
        TranficCalculator calculator = new TranficCalculator();
//        //设置策略模式
        calculator.setStrategy(new BusStrategy());
        //计算价格
        System.out.println("公交车乘16公里的价格:"+calculator.calculatePrice(16));
        //设置策略模式
        calculator.setStrategy(new TaxiStrategy());
        //计算价格
        System.out.println("出租车乘16公里的价格:"+calculator.calculatePrice(16));
    }


    CalculateStrategy mStrategy;

    public void setStrategy(CalculateStrategy mStrategy) {
        this.mStrategy = mStrategy;
    }
    public int calculatePrice(int km){
        return mStrategy.calculatePrice(km);
    }
}

这样代码就重构完成了,代码逻辑非常清晰,而且耦合性降低了,可扩展性变强了,现在如果增加一个出租车的方式,

//出租车计算策略
public class TaxiStrategy implements CalculateStrategy {
    @Override
    public int calculatePrice(int km) {
        return 2 * km;
    }
}

总结:
策略模式主要是用来分离算法,在相同的行为抽象下有不同的具体实现策略。这个模式很好地展示了开闭原则,也就是定义抽象,注入不同的实现,从而达到很好的可扩展性。
优点:

  • 结构清晰明了,使用简单直观
  • 耦合度相对而言较低,扩展方便
  • 操作封装也更为彻底,数据更安全

    缺点:

  • 随着策略模式的增加,子类也会变得繁多
  • 客户端必须知道所有的策略类,并自行决定使用哪一个策略类
  • Strategy和Context之间的通信开销

策略模式就到这里,大家对策略模式是不是又有了新的看法呢?
该文章参考《android源码设计模式解析与实战》这本书。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值