首頁>技術>

前言

大多數開發人員現在還在使用if else的過程結構,曾看過jdon的banq大哥寫的一篇文章,利用command,aop模式替代if else過程結構。當時還不太明白,這幾天看了《重構》第一章的影片租賃案例,感觸頗深。下面我來談一談為什麼要用state pattern替代if else,替代if else有什麼好處,以及給出詳細程式碼怎麼替代if else。

狀態模式簡介

意圖:允許物件在內部狀態發生改變時改變它的行為,物件看起來好像修改了它的類。

主要解決:物件的行為依賴於它的狀態(屬性),並且可以根據它的狀態改變而改變它的相關行為。

何時使用:程式碼中包含大量與物件狀態有關的條件語句。

如何解決:將各種具體的狀態類抽象出來。

需求

我們模仿商場根據不同日期來返回不同的價格,日期是不固定的,隨時可能要增加,優惠力度也不是固定的。

傳統if-else寫法
/** * 根據不同的日期狀態值獲取不同的折後價格 */public class IfElseCode {    private static int NORMAL = 1;//平時不打折    private static int CHRISTMAS = 2;//聖誕節打8折    private static int NEW_YEAR = 3;//新年打7折    /**     * 獲取價格     * @param dateCode 日期編碼     * @param fullMoney 原價     * @return 折後的價格     */    public BigDecimal getCharge(int dateCode, BigDecimal fullMoney) throws BusinessException{        if(NORMAL == dateCode){            return fullMoney.multiply(BigDecimal.valueOf(1));        }else if(CHRISTMAS == dateCode){            return fullMoney.multiply(BigDecimal.valueOf(0.8));        }else if(NEW_YEAR == dateCode){            return fullMoney.multiply(BigDecimal.valueOf(0.7));        }else {            throw new BusinessException("輸入的日期編碼有誤!");        }    }

缺點:如果有新增日期打折型別,就需要頻繁的修改此處的程式碼,不符合開閉原則!

三、使用狀態模式

3.1、定義狀態介面

/** * 狀態頂級介面 */public interface CashState {     void doAction(Context context);//初始化方法     BigDecimal getCharge(BigDecimal fullPrice);//獲取最終價格方法}

3.2、各個狀態實現類

/** * 日常不打折的狀態 */public class NormalState implements CashState {    @Override    public void doAction(Context context) {        context.setState(this);    }    @Override    public BigDecimal getCharge(BigDecimal fullPrice) {        return fullPrice.multiply(BigDecimal.valueOf(1));    }    public String toString(){        return "正常不打折";    }}
/** * 聖誕節的狀態 */public class ChristmasState implements CashState {    @Override    public void doAction(Context context) {        context.setState(this);    }    @Override    public BigDecimal getCharge(BigDecimal fullPrice) {        return fullPrice.multiply(BigDecimal.valueOf(0.8));    }    public String toString(){        return "聖誕節打8折";    }}
/** * 新年的狀態 */public class NewYearState implements CashState {    @Override    public void doAction(Context context) {        context.setState(this);    }    @Override    public BigDecimal getCharge(BigDecimal fullPrice) {        return fullPrice.multiply(BigDecimal.valueOf(0.7));    }    public String toString(){        return "新年打7折";    }}

3.3、定義上下文

/** * 上下文 */public class Context {    private CashState state;    public Context(){        state = null;    }    public void setState(CashState state){        this.state = state;    }    public CashState getState(){        return state;    }}

3.4、呼叫示例

public class StatePatternMain {    public static void main(String[] args) {        BigDecimal fullPrice = BigDecimal.valueOf(10);        Context context = new Context();        /**************日常不打折狀態************/        CashState normalState = new NormalState();        normalState.doAction(context);        System.out.println(context.getState().toString()                +" ,最終價格="+ context.getState().getCharge(fullPrice));        /**************聖誕節的狀態************/        CashState christmasState = new ChristmasState();        christmasState.doAction(context);        System.out.println(context.getState().toString()                +" ,最終價格="+ context.getState().getCharge(fullPrice));        /**************新年的狀態************/        CashState newYearState = new NewYearState();        newYearState.doAction(context);        System.out.println(context.getState().toString()                +" ,最終價格="+ context.getState().getCharge(fullPrice));     }}

3.5、結果展示

總結

應用例項:

1、打籃球的時候運動員可以有正常狀態、不正常狀態和超常狀態。

2、曾侯乙編鐘中,'鍾是抽象介面','鍾A'等是具體狀態,'曾侯乙編鐘'是具體環境(Context)。優點:

1、封裝了轉換規則。2、列舉可能的狀態,在列舉狀態之前需要確定狀態種類。

3、將所有與某個狀態有關的行為放到一個類中,並且可以方便地增加新的狀態,只需要改變物件狀態即可改變物件的行為。

4、允許狀態轉換邏輯與狀態物件合成一體,而不是某一個巨大的條件語句塊。

5、可以讓多個環境物件共享一個狀態物件,從而減少系統中物件的個數。

缺點:

1、狀態模式的使用必然會增加系統類和物件的個數。

2、狀態模式的結構與實現都較為複雜,如果使用不當將導致程式結構和程式碼的混亂。

3、狀態模式對"開閉原則"的支援並不太好,對於可以切換狀態的狀態模式,增加新的狀態類需要修改那些負責狀態轉換的原始碼,否則無法切換到新增狀態,而且修改某個狀態類的行為也需修改對應類的原始碼。

使用場景:

1、行為隨狀態改變而改變的場景。

2、條件、分支語句的代替者。

21
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • textCNN短文字分類-pytorch、torchtext