行為參數(shù)化

  • 行為參數(shù)化
    幫助你處理頻繁變更的需求的一種開發(fā)模式

篩選蘋果的例子

初試牛刀
  • 選擇綠色的蘋果
private List<Apple> inventory;

    @Before
    public void init() {
        inventory = asList(new Apple("red", 5), new Apple("green", 5), new Apple("red", 7));
    }

    /**
     * 過濾出青蘋果
     */
    @Test
    public void filterApple() {
        selectApple();
    }
    private void selectApple() {
        List<Apple> result = new ArrayList<>();
        for (Apple apple : inventory) {
            if (apple.getColor().equals("green")) {
                result.add(apple);
            }
        }
    }

如果說有一天需求改變了安接,需要選擇出紅蘋果怎么辦呢?
你可能認(rèn)為:把if改一下英融,copy一份不就好了嘛盏檐!這個確實能夠解決當(dāng)前問題,但是驶悟,第一:這個方案不優(yōu)雅胡野,如果客戶要求選擇重量咋辦,或者后面用戶還會提各種需要怎么辦痕鳍?這個程序的擴展性太差了硫豆。
第二:存在很多冗余的代碼,不易閱讀额获。

再展身手
  • 選擇青蘋果或者紅蘋果
 /**
     * 根據(jù)顏色過濾蘋果
     */
    @Test
    public void selectApple(String color) {
        selectWithColor(color);
    }
    private void selectWithColor(String color) {
        List<Apple> result = new ArrayList<>();
        for (Apple apple : inventory) {
            if (apple.getColor().equals(color)) {
                result.add(apple);
            }
        }
    }

主要就完美了嗎够庙?如果需要變成根據(jù)重量過濾怎么辦呢恭应?難道你還打算寫一個根據(jù)重量過濾的抄邀?那要是即根據(jù)顏色又根據(jù)重量過濾怎么辦呢?你難道還有根據(jù)兩個參數(shù)去判斷昼榛,那代碼也太混亂了境肾,一個方法不是去做一件事剔难,閱讀起來也晦澀難懂。
那應(yīng)該怎么做呢奥喻?請看參數(shù)行為化偶宫。

小小突破
  • 對行為進行抽象
public interface ApplePredicate {
    /**
     * 選擇蘋果
     *
     * @param apple
     * @return
     */
    boolean test(Apple apple);
}

抽象行為,本例是測試蘋果环鲤,具體怎么測試無需關(guān)心纯趋。有不同的子類去實現(xiàn)。

  • 對抽象行為的不同實現(xiàn)
public class ColorApplePredicate implements ApplePredicate {
    /**
     * 根據(jù)顏色過濾蘋果
     *
     * @param apple
     * @return
     */
    @Override
    public boolean test(Apple apple) {
        return apple.getColor().equals("green");
    }
}
public class WeightApplePredicate implements ApplePredicate {
    /**
     * 根據(jù)重量過濾蘋果
     *
     * @param apple
     * @return
     */
    @Override
    public boolean test(Apple apple) {
        return apple.getWeight() > 44;
    }
}

這些其實就是設(shè)計模式里面的策略模式冷离。所謂的策略模式也就是:定義一簇算法吵冒,把它們封裝起來(稱為策略),然后在運行時選擇一個算法運行西剥。

  • 選擇蘋果
public class StrategyApple {
    public static void main(String[] args) {
        List<Apple> inventory = asList(new Apple("red", 5), new Apple("green", 5), new Apple("red", 7));
        //根據(jù)顏色選擇蘋果
        List<Apple> apples = selectStrategyApple(inventory, new ColorApplePredicate());
        //根據(jù)重量選擇蘋果
        List<Apple> appleList = selectStrategyApple(inventory, new WeightApplePredicate());

    }

    /**
     * @param inventory 蘋果集合
     * @param predicate 操作的策略  或者是謂詞
     * @return
     */
    public static List<Apple> selectStrategyApple(List<Apple> inventory, ApplePredicate predicate) {
        List<Apple> result = new ArrayList<>();
        for (Apple apple : inventory) {
            if (predicate.test(apple)) {
                result.add(apple);
            }
        }
        return result;
    }
}

試想一下痹栖,如果用戶又加了需求,需要選擇顏色加重量或者其他的等等瞭空,我們只需要添加一種策略就可以輕松搞定揪阿,不需要沒用的copy,也不需要改動代碼的主體。
這真的就是最完美的了嗎咆畏?還有優(yōu)化的空間嗎南捂?
在上面這段代碼里我們可以看到,真正重要的是test這段代碼旧找,但令人遺憾的是它必須通過ApplePredicate來傳遞這種行為黑毅,也就是這種行為包裹在了ApplePredicate對象里面,而不是真正的傳遞行為钦讳。我們想一下lambda是實現(xiàn)的矿瘦。

//lambda
        List<Apple> lambdas = selectStrategyApple(inventory, apple -> apple.getColor().equals("green"));
        List<Apple> lambdastwo = selectStrategyApple(inventory, apple -> apple.getWeight() > 4);
        List<Apple> lambdasthree = selectStrategyApple(inventory,
            apple -> apple.getWeight() > 4 || apple.getColor().equals("green"));

從上面這段代碼我們可以看出,我們是真的把一段代碼愿卒,一種行為缚去,作為參數(shù)傳遞過去了。代碼清新琼开,易于閱讀易结,同時還少了很多沒必要的中間變量。

最后一次優(yōu)化

從目前的代碼來看還是只能使用蘋果柜候,要是換成梨子怎么辦呢搞动?不要告訴我copy一份,那要是再換成其他的呢渣刷?這也說明我們還有抽象的空間鹦肿。

   /**
     * 抽象處理
     *
     * @param inventory
     * @param predicate 操作的策略  或者是謂詞
     * @return
     */
    public static <T> List<T> selectStrategyT(List<T> inventory, Predicate<T> predicate) {
        List<T> result = new ArrayList<>();
        for (T t : inventory) {
            if (predicate.test(t)) {
                result.add(t);
            }
        }
        return result;
    }
說明一下 static <T> 不是返回值,表示傳入?yún)?shù)有泛型
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末辅柴,一起剝皮案震驚了整個濱河市箩溃,隨后出現(xiàn)的幾起案子瞭吃,更是在濱河造成了極大的恐慌,老刑警劉巖涣旨,帶你破解...
    沈念sama閱讀 221,406評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件歪架,死亡現(xiàn)場離奇詭異,居然都是意外死亡霹陡,警方通過查閱死者的電腦和手機和蚪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,395評論 3 398
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來烹棉,“玉大人惠呼,你說我怎么就攤上這事÷驮牛” “怎么了剔蹋?”我有些...
    開封第一講書人閱讀 167,815評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長辅髓。 經(jīng)常有香客問我泣崩,道長,這世上最難降的妖魔是什么洛口? 我笑而不...
    開封第一講書人閱讀 59,537評論 1 296
  • 正文 為了忘掉前任矫付,我火速辦了婚禮,結(jié)果婚禮上第焰,老公的妹妹穿的比我還像新娘买优。我一直安慰自己,他們只是感情好挺举,可當(dāng)我...
    茶點故事閱讀 68,536評論 6 397
  • 文/花漫 我一把揭開白布杀赢。 她就那樣靜靜地躺著,像睡著了一般湘纵。 火紅的嫁衣襯著肌膚如雪脂崔。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,184評論 1 308
  • 那天梧喷,我揣著相機與錄音砌左,去河邊找鬼。 笑死铺敌,一個胖子當(dāng)著我的面吹牛汇歹,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播偿凭,決...
    沈念sama閱讀 40,776評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼产弹,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了笔喉?” 一聲冷哼從身側(cè)響起取视,我...
    開封第一講書人閱讀 39,668評論 0 276
  • 序言:老撾萬榮一對情侶失蹤硝皂,失蹤者是張志新(化名)和其女友劉穎常挚,沒想到半個月后作谭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,212評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡奄毡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,299評論 3 340
  • 正文 我和宋清朗相戀三年折欠,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片吼过。...
    茶點故事閱讀 40,438評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡锐秦,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出盗忱,到底是詐尸還是另有隱情酱床,我是刑警寧澤,帶...
    沈念sama閱讀 36,128評論 5 349
  • 正文 年R本政府宣布趟佃,位于F島的核電站扇谣,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏闲昭。R本人自食惡果不足惜罐寨,卻給世界環(huán)境...
    茶點故事閱讀 41,807評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望序矩。 院中可真熱鬧鸯绿,春花似錦、人聲如沸簸淀。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,279評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽租幕。三九已至囊蓝,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間令蛉,已是汗流浹背聚霜。 一陣腳步聲響...
    開封第一講書人閱讀 33,395評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留珠叔,地道東北人蝎宇。 一個月前我還...
    沈念sama閱讀 48,827評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像祷安,于是被迫代替她去往敵國和親姥芥。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,446評論 2 359

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

  • 前言 《Java8實戰(zhàn)》不得不說是一本好書汇鞭,捧起來看起來就興奮得不想放下凉唐,其中介紹的函數(shù)式編程實在是太令人興奮了庸追,...
    我沒有三顆心臟閱讀 2,042評論 1 0
  • 在實習(xí)的這一段時間里,我深刻體會到一個道理台囱,就是用戶的需求不斷的在變化淡溯,因而自己的代碼也要進行重構(gòu),這說明了一個問...
    freelands閱讀 3,440評論 8 9
  • 如何應(yīng)對不斷變化的需求 軟件工程中,用戶的需求肯定會變强品,如何應(yīng)對不斷變化的需求膘侮,理想狀態(tài)下,應(yīng)該把工作量降到最少的榛,...
    小Noodles閱讀 1,319評論 0 0
  • 什么是行為參數(shù)化琼了? 行為參數(shù)化就是可以幫助你處理頻繁變更的需求的一種軟件開發(fā)方式。它意味著拿出一個代碼塊夫晌,把它準(zhǔn)備...
    1桶閱讀 951評論 0 6
  • 基礎(chǔ)概念 在軟件工程中雕薪,一個眾所周知的問題是,不管你做什么慷丽,用戶的需求肯定會變蹦哼。行為參數(shù)化就是可以幫助你處理頻繁變...
    依然愛笑的薰衣草閱讀 202評論 0 0