Android设计模式之策略模式

作为一个菜鸟,每次自己写完代码后,回头一看发现自己的代码实在太乱了,不仅阅读起来很困难,而且以后改逻辑的话改起来也特别的麻烦,所以买了一本设计模式的书,自己没事就看看,最近看到了策略模式,所以就想写一写,若是写的不好还望大家见谅。
一、策略模式的定义:
策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以互相替换。策略模式让算法独立于使用它的客户而独立变化。
二、策略模式的使用场景:
1、针对于一类型问题的多种处理方式,仅仅是具体行为有差别时。
2、需要安全地封装多种同一类型的操作时。
3、出现同一抽象类有多个子类,而又需要使用if-else或者switch-case来选择具体子类时。
三、策略模式的简单实现:
下面我们来使用传统模式和策略模式实现同一功能,看看策略模式有什么优势。
模拟需求:北京坐公共交通工具的费用计算
下面是传统模式的实现方式:

package com.shaoen.lenovo.stragety;

import android.support.v7.app.AppCompatActivity;
import android.util.Log;

public class PriceCalculator extends AppCompatActivity {

    private static final String TAG=PriceCalculator.class.getSimpleName();
    //公交车类型
    private static final int BUS=1;
    //地铁类型
    private static final int SUBWAY=2;
    public static void main(String[] args){
        PriceCalculator calculator=new PriceCalculator();
        Log.i(TAG, "做16公里的公交车票价为: "+calculator.calculatePrice(16,BUS));
        Log.i(TAG, "做16公里的地铁车票价为: "+calculator.calculatePrice(16,SUBWAY));
    }
    private int calculatePrice(int km ,int type){
        if (type==BUS){
            return busPrice(km);
        }else if(type==SUBWAY){
          return  subwayPrice(km);
        }
        return  0;
    }

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

    /**
     * 6公里内3元,6-12公里4元,12-22公里5元,22-32公里6元,最高7元
     * @param km
     * @return
     */
    private 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;
        }
        return 7;
    }

}

PriceCalulator类很明显的问题就是并不是单一职责,首先它承担了计算公交车和地铁乘坐价格的职责;另一个问题时通过if-else的形式来判断使用哪种计算形式。当我们增加一种出行方式时,比如出租车,那么我们就需要在PriceCalulator中增加一个方法来计算出租车出行的价格,并且在calcalatePrice(int km,int type)函数中增加一个判断,添加的代码如下:

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

    /**
     * 简单的计算为每公里2元
     * @param km
     * @return
     */
    private int taxiPrice(int km){
        return  km*2;
    }

此时的代码已经比较混乱,各种if-else语句缠绕其中,当价格的计算方法变化时,需要直接修改类中的代码,那么有可能有一段代码是其他几个计算方法公用的,这就容易引入错误,同样在增加出行方式时,也容易发生错误。
下面我们看一下使用策略模式重构代码的格式:

计算的接口

public interface CalculateStrategy {
    /**
     * 按公里计算价格
     * @param km
     * @return
     */
    int calculatePrice(int km);
}

计算的具体类

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;
        }
        return 7;
    }
}
public class BusStrategy implements  CalculateStrategy {
    @Override
    public int calculatePrice(int km) {
        //超过十公里的总距离
        int extraTotal=km-10;
        //超过的距离是5公里的倍数
        int extraFator=extraTotal/5;
        //超过的距离对5公里的余数
        int fraction=extraTotal%5;
        //价格计算
        int price =1+extraFator*1;
        return fraction>0?++price :price;
    }
}

主程序:

public class PriceCalculator2 extends AppCompatActivity {

    private static final String TAG=PriceCalculator2.class.getSimpleName();
    public static void main(String[] args){
        PriceCalculator2 calculator=new PriceCalculator2();
        calculator.setCalculateStrategy(new BusStrategy());
        Log.i(TAG, "做16公里的公交车票价为: "+calculator.calculatePrice(16));
    }

    private CalculateStrategy calculateStrategy;
    private void setCalculateStrategy(CalculateStrategy calculateStrategy){
        this.calculateStrategy=calculateStrategy;
    }
    public int calculatePrice(int km){
        return calculateStrategy.calculatePrice(km);
    }
}

上面就是策略模式的实现方式,由代码可以看出,虽然类是多了点,但是清晰度及扩展性增强了许多,少了if-else语句,结构变得清晰了,这时候如果再增加一种出租车的出行方式的话,我们直接加一个实现类就可以了,扩展性很强,而且不会动其他我们已经完成的代码,不易出错。

其实策略模式的使用范围非常广,比如在ImageLoader里,其实就有这种实现,比如设置图片的顺序加载与逆序加载。

总结:通过上面两种方式可以得出:前者通过if-else来解决问题,虽然实现较为简单,类型层级单一,但暴露的问题非常明显,即代码臃肿,逻辑复杂,难以升级和维护没有结构可言。厚泽则是通过建立抽象,将不同的策略构建成一个具体的策略实现,通过不同的策略实现算法替换。在简化逻辑、结构的同时,增强了系统的可读性、稳定性、可扩展性,这对于较为复杂的业务逻辑显得更为直观,扩展也更为方便。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值