策略模式

什么是策略模式?

策略模式定義了算法族,分別封裝起來,讓他們之間可以相互替換,此模式讓算法的變化獨立于使用算法的客戶

設(shè)計原則

  1. 找出變化之處酥泛,把它們獨立出來
  2. 針對接口編程,而不是針對實現(xiàn)編程
  3. 多用組合,少用繼承

模擬鴨子游戲

SimUDuck,游戲中會出現(xiàn)各種鴨子柔袁,一邊游泳戲水呆躲,一邊呱呱叫。

使用面向?qū)ο蟮脑O(shè)計模式:設(shè)計鴨子的超類BaseDuck,并讓各種鴨子繼承此超類

public abstract class BaseDuck {
   abstract void display();
}

野鴨子MallardDuck:

public class MallardDuck extends BaseDuck {
    void display() {
        // 我是綠頭鴨
    }
    ...
}

紅頭鴨子RedheadDuck:

public class RedheadDuck extends BaseDuck {
    void display() {
        // 我是紅頭鴨子
    }
    ...
}

現(xiàn)在我們的讓鴨子能飛

  • 方案一:父類增加
public abstract class BaseDuck {
    abstract void display();
    public void fly() {
        // 飛行,可復(fù)用
    };
}

問題:并不是所有的鴨子都能飛

  • 方案二:繼承
public abstract class BaseDuck {
    abstract void display();
    abstract void fly();
}

問題:每個子類都需要重寫, 無法復(fù)用

public class RubberDuck extends BaseDuck {
    void display() { 
        // 橡皮鴨 
    }
    void fly() {
        // 覆蓋瘦馍,什么都不做
    }
}
public class DecoyDuck extends BaseDuck {
    void display() { 
        // 誘餌鴨
    }
    void fly() {
        // 覆蓋歼秽,什么都不做
    }
}
  • 方案三:利用接口应役,同時增加鴨子叫接口
public interface Flyable {
    fly();
}

public interface Quackable {
    quack();
}
public MallardDuck extends BaseDuck implements Flyable, Quackable {
    void fly() {
        // 翅膀飛行
    }
    
    void quack() {
        // 呱呱叫
    }
}

問題:重復(fù)的代碼越來越多

解決方案

使用設(shè)計原則一:封裝變化
使用設(shè)計原則二:針對接口編程

  • 抽取變化部分為接口
public interface FlyBehavior {
    void fly();
}

public interface QuackBehavior {
    void quack();
}
  • 把每個行為實現(xiàn)單獨作為一個類
public class FlyWithWings implments FlyBehavior {
    void fly() {
        // 使用翅膀飛行
    }
}

public class FlyNoWay implments FlyBehavior {
    void fly() {
        // 什么都不做情组,不會飛!
    }
}

public class Quack implments QuackBehavior {
    void quack() {
        // 鴨子呱呱叫
    }
}

public class Squeak implments QuackBehavior {
    void quack() {
        // 橡皮鴨子吱吱叫
    }
}

public class MuteQuack implments QuackBehavior {
    void quack() {
        // 什么都不做箩祥,不會叫
    }
}
  • 從新定義鴨子超類
public abstract class Duck {
    FlyBehavior flyBehavior;
    QuackBehavior quackBehavior;

    void display();
    public void performFly(){
        if (flyBehavior != null) {
            flyBehavior.fly();
        }
    }
    
    public void performQuack(){
        if (quackBehavior != null) {
            quackBehavior.quack();
        }
    }
}
  • 定義鴨子的實體類
public class MallardDuck extends BaseQuack {
    public MallardDuck() {
        // 將鴨子的飛的行為和叫的行為院崇,委托給行為類
        flyBehavior = new FlyBehavior();
        quackBehavior = new QuackBehavior();
    }

    void display() {
        // 野鴨子
    }
}
public class Test {
    public static void main(String[] args){
        Duck duck = new MallardDuck();
        duck.performFly();
        duck.performQuack();
    }
}

問題:MallardDuck內(nèi)部還是使用了針對實現(xiàn)編程

解決方案

  • 在超類鴨子中增加兩個方法
public abstract class Duck {
    ...
    public void setFlyBehavior(FlyBehavior flyBehavior) {
        this.flyBehavior = flyBehavior;
    }
    
    public void setQuackBehavior(QuackBehavior quackBehavior) {
        this.quackBehavior = quackBehavior;
    }
}

  • 動態(tài)設(shè)置行為
public class Test {
    public static void main(String[] args){
        Duck duck = new MallardDuck();
        duck.setFlyBehavior(new FlyWithWings());
        duck.setQuackBehavior(new Quack());
        duck.performFly();
        duck.performQuack();
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市袍祖,隨后出現(xiàn)的幾起案子底瓣,更是在濱河造成了極大的恐慌,老刑警劉巖蕉陋,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件捐凭,死亡現(xiàn)場離奇詭異,居然都是意外死亡凳鬓,警方通過查閱死者的電腦和手機茁肠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來缩举,“玉大人垦梆,你說我怎么就攤上這事〗龊ⅲ” “怎么了托猩?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長辽慕。 經(jīng)常有香客問我京腥,道長,這世上最難降的妖魔是什么溅蛉? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任公浪,我火速辦了婚禮,結(jié)果婚禮上温艇,老公的妹妹穿的比我還像新娘因悲。我一直安慰自己,他們只是感情好勺爱,可當(dāng)我...
    茶點故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布晃琳。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪卫旱。 梳的紋絲不亂的頭發(fā)上人灼,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天,我揣著相機與錄音顾翼,去河邊找鬼投放。 笑死,一個胖子當(dāng)著我的面吹牛适贸,可吹牛的內(nèi)容都是我干的灸芳。 我是一名探鬼主播,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼拜姿,長吁一口氣:“原來是場噩夢啊……” “哼烙样!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蕊肥,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤谒获,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后壁却,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體批狱,經(jīng)...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年展东,在試婚紗的時候發(fā)現(xiàn)自己被綠了赔硫。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,013評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡琅锻,死狀恐怖卦停,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情恼蓬,我是刑警寧澤惊完,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站处硬,受9級特大地震影響小槐,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜荷辕,卻給世界環(huán)境...
    茶點故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一凿跳、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧疮方,春花似錦控嗜、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽曾掂。三九已至,卻和暖如春壁顶,著一層夾襖步出監(jiān)牢的瞬間珠洗,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工若专, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留许蓖,地道東北人。 一個月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓调衰,卻偏偏與公主長得像膊爪,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子窖式,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,960評論 2 355

推薦閱讀更多精彩內(nèi)容