「设计模式」策略模式

这是我参与更文挑战的第7天,活动详情查看: 更文挑战

定义

笼统的来说策略模式是定义了一系列算法,并将每一个算法封装起来,而且使它们之间可以相互替换,策略模式让算法独立于使用它的客户而独立变化

使用场景

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

直白点讲就是大量的if-else 或者 switch-case的情况下,并且他们都有很多共同点,这个时候就可以考虑使用策略模式,把它们封装起来,根据不同的策略选择不同的操作

代码实现

我们先看一段代码,有关出行的;


public class PriceCalculator {
    private static final int BUS = 1; //公交车类型
    private static final int SUBWAY = 2;//地铁类型

    //公交车价格计算
    private static int busPrice(int km) {
        int extraTotal = km - 10;  //超过10公里总距离
        int extraFactor = extraTotal / 5;  //超过的距离是5公里的倍数
        int fraction = extraTotal % 5; //超过的公里对5公里取余数
        int price = 1 + extraFactor * 1;//价格计算

        return (fraction > 0) ? ++price : price;
    }

    //地铁价格计算
    public static int subwayPrice(int km) {
        if (km <= 6) {
            return 3;
        } else if (km > 6 && km < 12) {
            return 4;
        } else if (km > 12 && km < 22) {
            return 5;
        } else if (km > 22 && km < 32) {
            return 6;
        } else {
            return 7;
        }

    }
    //计算价格
    public static int calculatePrice(int km, int type) {
        if (type == BUS) {
            return busPrice(km);
        } else if (km == SUBWAY) {
            return subwayPrice(km);
        }
        return 0;
    }

    public static void main(String[] args) {
        PriceCalculator priceCalculator = new PriceCalculator();
        System.out.println("坐19公里的公交车票价格为:" + priceCalculator.busPrice(19));
        System.out.println("坐19公里的地铁票价格为:" + priceCalculator.subwayPrice(19));
    }
}

复制代码

策略模式1.png

看上面的代码,如果我们想计算出租车出行的价格,或者飞机,火车,动车等等.是不是需要改类,然后写各种if-else判断呢? 这个时候PriceCalculator 很明显就不是单一职责了.它既要计算交通工具乘坐价格,还要if-else判断是哪一种出行攻击.

然后我们用策略模式优化下上边的代码:
新建一个策略的抽象,用来定义计算价格的接口:

//定义一个计算价格的抽象策略接口
public interface CalculateStrategy {
    /**
     * 按照距离计算价格
     * @param km 公里
     * @return 返回价格
     */
    int calculatePrice(int km);
}
复制代码

然后定义具体的实现策略:Bus/Subway/Taxi 等等

public class BusStrategy implements CalculateStrategy {
    @Override
    public int calculatePrice(int km) {  //北京公交车 10公里之内1元,超过10公里之后每增加1元可以乘坐5公里
        int extraTotal = km - 10;  //超过10公里总距离
        int extraFactor = extraTotal / 5;  //超过的距离是5公里的倍数
        int fraction = extraTotal % 5; //超过的公里对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 > 6 && km < 12) {
            return 4;
        } else if (km > 12 && km < 22) {
            return 5;
        } else if (km > 22 && km < 32) {
            return 6;
        } else {
            return 7;
        }
    }
}
复制代码
//TAXI 计算策略类
public class TaxiStrategy implements CalculateStrategy {
    @Override
    public int calculatePrice(int km) {
        return km * 2;
    }
}
复制代码

然后定义个操作策略的类:

//操作策略的上下文环境
public class TranficCalculator {

    public static void main(String[] args) {
        TranficCalculator tranficCalculator = new TranficCalculator();
        tranficCalculator.setCalculateStrategy(new BusStrategy());
        System.out.println("公交车19公里的价格:" + tranficCalculator.calculatePrice(19));
        tranficCalculator.setCalculateStrategy(new TaxiStrategy());
        System.out.println("Taxi19公里的价格:" + tranficCalculator.calculatePrice(19));
    }
    private CalculateStrategy calculateStrategy;

    public void setCalculateStrategy(CalculateStrategy calculateStrategy) {
        this.calculateStrategy = calculateStrategy;
    }

    public int calculatePrice(int km) {
        return calculateStrategy.calculatePrice(km);
    }
}

复制代码

是不是清晰明了,需要计算新的出行方式价格,之需要定义新的具体策略类,然后计算, 在操作对象中传递获取就好了.

总结

通过建立抽象接口,将不同的策略构建成一个个具体的策略实现,通过不同的策略实现算法替换,在简化逻辑,结构的同时,增强了代码的可读性,系统的稳定性,可扩展性.后期接手开发的人员能直观的看懂逻辑代码,维护也超级方便

优点
  • 结构清晰明了,使用简单直观.
  • 耦合度相对之前的代码来说较低,扩展方便,可以快速扩展.
  • 操作封装更为彻底,数据更加安全,类职责单一.
缺点
  • 随着策略的增加,子类也变得多,增加类的代码量.

后话

RecyclerView 提供了一个新的组件 ConcatAdapter,内部是通过策略模式来区分不同的ViewType ,然后加载不同的Item,感兴趣的话可以了解了解. 后续会出分析文章.

以上就是策略模式模式的全部内容啦, 如果觉得写得不错,不妨点个赞.

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享