Android設(shè)計(jì)模式—策略模式與狀態(tài)模式

策略模式和狀態(tài)模式都比較簡(jiǎn)單好理解,都是為了解決一個(gè)問題有多種方案這樣的場(chǎng)景,兩者結(jié)構(gòu)幾乎一樣。

不同的是狀態(tài)模式的行為是平行的,不可替換的,一種狀態(tài)就明確對(duì)應(yīng)一種行為。
而策略模式的行為是彼此獨(dú)立、可相互替換的。一種是抽象狀態(tài),一種是抽象策略。

一、策略模式

1. 定義

策略模式定義了一系列的算法,并將每一個(gè)算法封裝起來,使它們可以相互替換。策略模式讓算法獨(dú)立于使用它的客戶而獨(dú)立變化。

如果將所有算法都放在一個(gè)類中,使用if-else或者switch來判斷使用哪一個(gè),就會(huì)使程序變得非常繁雜,并且這個(gè)類使用了多種計(jì)算方式違背了單一指責(zé)原則。如果想要增加一個(gè)算法,就必須修改原先封裝好的代碼,可擴(kuò)展性差,這就出現(xiàn)了策略模式

2. 應(yīng)用場(chǎng)景

  1. 針對(duì)同一類型問題的多種處理方式,僅僅是具體行為有差別時(shí)。
  2. 需要安全地封裝多種同一類型的操作。

3. 實(shí)現(xiàn)

UML

抽象策略類
public interface CalculateStrategy {
    int calculatePrice(int km);
}
具體策略類
public class BusStrategy implements CalculateStrategy {
    @Override
    public int calculatePrice(int km) {
        int price = 0;
        // 具體算法
        return price;
    }
}
public class SubwayStrategy implements CalculateStrategy {
    @Override
    public int calculatePrice(int km) {
        int price = 0;
        // 具體算法
        return price;
    }
}
使用
public class TrafficCalculator {
    public static void main(String[] args) {
        TrafficCalculator calculator = new TrafficCalculator();
        calculator.setStrategy(new CarStrategy());
        calculator.calculatePrice(55);
    }

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

}

4. 小結(jié)

策略模式主要用來分離算法,在相同的行為抽象下有不同的具體實(shí)現(xiàn)策略。這個(gè)模式很好地演示了開閉原則,也就是定義抽象,注入不同的實(shí)現(xiàn),從而達(dá)到很好的可擴(kuò)展性。

優(yōu)點(diǎn)

  1. 結(jié)構(gòu)清晰、使用簡(jiǎn)單直觀。
  2. 耦合度相對(duì)而言較低,擴(kuò)展方便。
  3. 操作封裝徹底,數(shù)據(jù)更為安全。

缺點(diǎn)

  1. 隨著策略的增加,子類會(huì)變得繁多。

二、狀態(tài)模式

1. 定義

當(dāng)一個(gè)對(duì)象的內(nèi)在狀態(tài)改變時(shí)允許改變其行為,這個(gè)對(duì)象看起來像是改變了其類。

2. 使用場(chǎng)景

  1. 一個(gè)對(duì)象的行為取決于它的狀態(tài),必須在運(yùn)行時(shí)由狀態(tài)覺得行為。
  2. 代碼中包含大量與狀態(tài)有關(guān)的條件語句。

3. 實(shí)現(xiàn)

UML
狀態(tài)抽象類
public interface TvState {
    void nextChannel();
    void prevChannel();
    void turnUp();
    void turnDown();
}
具體狀態(tài)類

關(guān)機(jī)狀態(tài)下什么都做不了。

public class PowerOffState implements TvState {
    @Override
    public void nextChannel() { }

    @Override
    public void prevChannel() { }

    @Override
    public void turnUp() { }

    @Override
    public void turnDown() { }
}
public class PowerOnState implements TvState {
    @Override
    public void nextChannel() {
        System.out.println("下一個(gè)");
    }

    @Override
    public void prevChannel() {
        System.out.println("上一個(gè)");
    }

    @Override
    public void turnUp() {
        System.out.println("調(diào)大");
    }

    @Override
    public void turnDown() {
        System.out.println("調(diào)小");
    }
}
電源
public interface PowerController {
    void powerOn();
    void powerOff();
}
控制

封裝了狀態(tài)決定行為的實(shí)現(xiàn)。

public class TvController implements PowerController {
    private TvState mTvState;

    public void setTvState(TvState tvState) {
        mTvState = tvState;
    }

    @Override
    public void powerOn() {
        setTvState(new PowerOnState());
    }

    @Override
    public void powerOff() {
        setTvState(new PowerOffState());
    }

    public void nextChannel() {
        mTvState.nextChannel();
    }

    public void prevChannel() {
        mTvState.prevChannel();
    }

    public void turnUp() {
        mTvState.turnUp();
    }

    public void turnDown() {
        mTvState.turnDown();
    }
    
}
調(diào)用代碼
public class Test {
    public static void test() {
        TvController controller = new TvController();
        controller.powerOn();
        controller.nextChannel();
        controller.powerOff();
        controller.turnUp();
    }
}

4. 小結(jié)

狀態(tài)模式應(yīng)用還是很廣泛的,在最常見的登錄模塊就可以使用,去避免重復(fù)判斷登錄狀態(tài)和未登錄狀態(tài)。使用狀態(tài)模式可以消除重復(fù)的if-else邏輯、結(jié)構(gòu)更為清晰,也使這個(gè)模塊的可擴(kuò)展性和靈活性更高。

優(yōu)點(diǎn)

  1. 將與一個(gè)特定狀態(tài)相關(guān)的行為都放入一個(gè)狀態(tài)對(duì)象中,更好地組織與特定狀態(tài)的行為相關(guān)的代碼。
  2. 繁瑣的狀態(tài)判斷轉(zhuǎn)換成狀態(tài)類族,避免代碼膨脹,保證可擴(kuò)展性和可維護(hù)性。

缺點(diǎn)

  1. 會(huì)增加系統(tǒng)類和對(duì)象的個(gè)數(shù)。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 設(shè)計(jì)模式概述 在學(xué)習(xí)面向?qū)ο笃叽笤O(shè)計(jì)原則時(shí)需要注意以下幾點(diǎn):a) 高內(nèi)聚、低耦合和單一職能的“沖突”實(shí)際上,這兩者...
    彥幀閱讀 3,879評(píng)論 0 14
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,872評(píng)論 25 709
  • 參考資料:菜鳥教程之設(shè)計(jì)模式 設(shè)計(jì)模式概述 設(shè)計(jì)模式(Design pattern)代表了最佳的實(shí)踐,通常被有經(jīng)驗(yàn)...
    Steven1997閱讀 1,267評(píng)論 1 12
  • 終端 總結(jié):1.測(cè)試.ssh -T git@github.com 此結(jié)果可忽略. 2.ssh-add id_rsa...
    sfandy閱讀 381評(píng)論 0 0
  • 年年歲歲花相似,歲歲年年人不同,時(shí)間過的很快,五一又來到了,然而這個(gè)五一卻和往年有些不同。 第一件大事,第一次當(dāng)伴...
    心羽暖姐姐閱讀 169評(píng)論 0 2

友情鏈接更多精彩內(nèi)容