策略模式2

我們?cè)倏匆粋€(gè)策略模式的代碼,深度理解下

//對(duì)象父類,鴨子
public abstract class Duck {
    IQuackBehavior quackBehavior;    //行為的引用

    public abstract void display();

    public void performQuack() {
        quackBehavior.quack();
    }
    public void setQuackBehavior(IQuackBehavior quackBehavior) {
        this.quackBehavior = quackBehavior;
    }
}
//具體的子類,綠頭鴨
public class DuckMallard extends Duck {
    @Override
    public void display() {
        System.out.println("我是 綠頭鴨");
    }
}

//行為的接口,叫喊接口
public interface IQuackBehavior {
    void quack();
}
//行為實(shí)現(xiàn)1
public class MuteQuack implements IQuackBehavior{
    @Override
    public void quack() {
        System.out.println("不會(huì)發(fā)出聲音");
    }
}
//行為實(shí)現(xiàn)2
public class SqueckQuack implements IQuackBehavior {
    @Override
    public void quack() {
        System.out.println("發(fā)出吱吱的聲音");
    }
}
//場(chǎng)景驗(yàn)證
public class TestSimulator {
    public static void main(String[] args) {
        Duck duck = new DuckMallard();
        duck.setQuackBehavior(new SqueckQuack());
        duck.display();
        duck.performQuack();
    }
}
image.png

上面是headFirst里關(guān)于策略的用例。我們可以一起來(lái)看看代碼為什么這樣寫。

1、找出可能的變化之處,把他們獨(dú)立出來(lái),不要和不變的放在一起。

所以我們可以看出,把display()方法我們放在了父類里,但是卻把叫喊的行為單獨(dú)抽象出來(lái)作為行為類。
因?yàn)閐isplay是所有子類都有的;而叫喊如果放在父類里會(huì)導(dǎo)致子類都要去重寫,有些子類沒(méi)有也要重寫一個(gè)。

這一步我們將行為單獨(dú)出來(lái)了

2、針對(duì)接口編程,不要針對(duì)實(shí)現(xiàn)編程

什么意思呢?以前我們的做法是在父類里定義抽象接口,子類去實(shí)現(xiàn),但是這種方式,我們就被實(shí)現(xiàn)綁的死死的,沒(méi)辦法更改行為。我們?yōu)槭裁床粚⑿袨樵谶\(yùn)行的時(shí)候再給他,還可以讓子類可以改變自己的行為。

這一步我們確定行為使用接口而不是采用繼承和實(shí)現(xiàn)

3、盡可能采用組合,將行為委托到其他類

我們?cè)诟割惱镆昧诵袨榈慕涌谝?,并定義了方法,在方法里通過(guò)引用去調(diào)用對(duì)應(yīng)的行為。
這塊是策略模式變行最多的地方,我們可以有多種方式進(jìn)行引用。第一種通過(guò)構(gòu)造函數(shù),第二種通過(guò)set賦值(同上),第三者可以直接在方法上入?yún)⒁?/p>

//通過(guò)構(gòu)造函數(shù)
public class DuckMallard extends Duck {
    public DuckMallard(IQuackBehavior quackBehavior){
        this.quackBehavior=quackBehavior;
    }
    @Override
    public void display() {
        System.out.println("我是 綠頭鴨");
    }
}
  public static void main(String[] args) {
        Duck duck = new DuckMallard(new SqueckQuack());
        duck.display();
        duck.performQuack();
    }

//通過(guò)方法引用
public abstract class Duck {
    public abstract void display();
    public void performQuack(IQuackBehavior quackBehavior) {
        quackBehavior.quack();
    }
}
    public static void main(String[] args) {
        Duck duck = new DuckMallard();
        duck.display();
        duck.performQuack(new SqueckQuack());
    }

在java里很多時(shí)候策略模式都是這樣用的,直接創(chuàng)建一個(gè)新的策略賦值進(jìn)去

    public static void main(String[] args) {
        Duck duck = new DuckMallard();
        duck.setQuackBehavior(new IQuackBehavior() {
            @Override
            public void quack() {
                System.out.println("我就是這樣叫的");
            }
        });
        duck.display();
        duck.performQuack();
    }

在策略模式(Strategy Pattern)中,一個(gè)類的行為或其算法可以在運(yùn)行時(shí)更改。這種類型的[設(shè)計(jì)模式]屬于行為型模式。簡(jiǎn)單理解就是一組算法,可以互換,再簡(jiǎn)單點(diǎn)策略就是封裝算法。

模式結(jié)構(gòu)的主要特征

1、有一個(gè)行為接口,同時(shí)還有很多策略實(shí)現(xiàn)
2、持有了抽象接口的引用

策略模式的優(yōu)點(diǎn)和缺點(diǎn)

優(yōu)點(diǎn):算法可以隨時(shí)切換,擴(kuò)展性好
缺點(diǎn):策略類會(huì)很多

如何解決策略膨脹

?著作權(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)容

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