java8之通過行為參數(shù)化傳遞代碼

在實習(xí)的這一段時間里,我深刻體會到一個道理,就是用戶的需求不斷的在變化,因而自己的代碼也要進(jìn)行重構(gòu),這說明了一個問題,我設(shè)計的代碼不夠好。所以,我覺得作為程序員來說,很重要的一點(diǎn)就是,讓你的代碼能夠適應(yīng)變化。

行為參數(shù)化

行為參數(shù)化,就是可以幫助我們處理頻繁變化需求的一種軟件開發(fā)模式,通俗的說,就是拿出一個代碼塊,把它準(zhǔn)備好,卻不去執(zhí)行它。這個代碼塊以后可以被程序的其他部分調(diào)用,這就意味著我們可以推遲這塊代碼的執(zhí)行。

背景

農(nóng)場里有很多蘋果,我們要去篩選特定的蘋果,并記錄下來。接下來,我們通過不斷變化的需求來重構(gòu)我們的代碼。以下的場景都是我虛擬出來的,便于故事的發(fā)展,哈哈。

片段一

開始的別人給我們提出的需求是,篩選出來所有顏色是綠色的蘋果。我心里想,你是不是鄙視我,這么簡單,遍歷一下把綠色蘋果放到新的集合不就行了嗎?我可是程序員哎,不是來打雜的,我可是要寫牛逼的代碼的。算了,還是寫吧。代碼如下:

 public static List<Apple> filterGreenApples(List<Apple> inventory) {
        List<Apple> result = new ArrayList<>();
        for (Apple apple : inventory) {
            if ("green".equals(apple.getColor())) {
                result.add(apple);
            }
        }
        return result;
    }

我把代碼提交上去了,然后屁顛屁顛的做其他事情了,好像完成了一個很大的項目。。。

片段二

第二天,那個人又找到我,說道,你能不能實現(xiàn)一個篩選紅色蘋果的接口。
  我心里自言自語,臥槽,這需求變化那么快,昨天蘋果還是綠的,今天就變紅了,尼瑪,這萬惡的商家,催熟劑就是厲害。以后吃蘋果還是吃青的吧。開始我準(zhǔn)備把上面的代碼copy下來,然后"green"改成"red",但是仔細(xì)一想,萬一明天,讓我寫一個黑蘋果的接口,那我不又要寫一個。于是把color抽象出來,變成一個參數(shù)傳進(jìn)來,這樣你要什么顏色的我都有了。突然,發(fā)現(xiàn)自己好厲害,抽象我都會。。。自我陶醉中。代碼如下:

  public static List<Apple> filterApplesByColor(List<Apple> inventory, String color) {
        List<Apple> result = new ArrayList<>();
        for (Apple apple : inventory) {
            if (color.equals(apple.getColor())) {
                result.add(apple);
            }
        }
        return result;
    }

寫完之后,我心里在那嘀咕,萬惡的資本主義,我把顏色都抽象出來了,看你需求怎么變。哥,可是--程序員。

片段三

晚上回去睡個安穩(wěn)覺后,第二天,那人又來了,對,還是那個男人。我問他,是不是我寫的接口不行。那人回到到,不是,是這邊又有新的需求。突然之間,整個人都傻了。還有需求,算了,誰讓我是程序員呢。之后,他和我說道,新的需求是區(qū)分,大蘋果和小蘋果,大蘋果是重量大于500g的。二話沒說,扭頭就去擼代碼。代碼如下:

public static List<Apple> filterApplesByWeight(List<Apple> inventory, int weight) {
        List<Apple> result = new ArrayList<>();
        for (Apple apple : inventory) {
            if (apple.getWeight() > weight) {
                result.add(apple);
            }
        }
        return result;
    }

聰明的我,早已想到需求會變,這次直接把這個接口抽象好,內(nèi)心不禁有暗暗自喜。想到世界還有自己這種程序員,就說明世界還有希望。

片段四

第二天,他又來了,我知道,又要干活了。新的需求是,過濾那些紅色的且重量大于500g的蘋果。代碼如下:

 public static List<Apple> filterApples(List<Apple> inventory, String color, int weight) {
        List<Apple> result = new ArrayList<>();
        for (Apple apple : inventory) {
            if (color.equals(apple.getColor()) && apple.getWeight() > weight) {
                result.add(apple);
            }
        }
        return result;
    }

不一會我就設(shè)計好了,但是卻沒有之前的開心了,不知道明天又會有什么新的需求,寶寶心里好苦啊。

片段五

之后令我很驚訝的是,沒有新的需求提出了,我一遍暗地自喜,一遍在思考一個問題。為什么,需求變,我的代碼就要變化那么大呢?需求都是和選擇蘋果相關(guān),選擇什么樣的蘋果是通過參數(shù)來傳遞的,那么有沒有一種方法,通過一個借口來實現(xiàn)傳遞不同的參數(shù)呢?
  如果熟悉設(shè)計模式的你,應(yīng)該能想到策略模式。接口一致,按需傳遞該接口對應(yīng)的實例。也是面向接口編程的一種體現(xiàn)。先設(shè)計一個接口,用來承載選擇蘋果的邏輯,代碼如下:

public interface ApplePredicate {
    boolean test(Apple apple);
}

現(xiàn)在我們可以用不同的實現(xiàn)來傳遞不同的邏輯了,如下:

//綠色蘋果
public class GreenApplePredicate implements ApplePredicate {
    @Override
    public boolean test(Apple apple) {
        return apple.getColor().equals("green");
    }
}

//大蘋果
public class BigApplePredicate implements ApplePredicate {
    @Override
    public boolean test(Apple apple) {
        return apple.getWeight() > 500;
    }
}

//代碼主體
public static List<Apple> filterApples(List<Apple> inventory, ApplePredicate p) {
        List<Apple> result = new ArrayList<>();
        for (Apple apple : inventory) {
            if (p.test(apple)) {
                result.add(apple);
            }
        }
        return result;
    }

可以看出,代碼主體以后我們就不會改變了,只要通過傳入不同的行為(過濾邏輯),就行了,而且這里只傳遞一個參數(shù),卻可以傳遞多種行為,多種行為,一個參數(shù),是不是很nice。我又開始沾沾自喜。。感覺自己又變得厲害了,晚上回去睡得很任性。

片段六

第二天,還是沒有新的需求,我們都知道,程序員沒事做,這寶貴的資源就白白的浪費(fèi),別人不心疼,我都心疼。于是,自己又去搗鼓昨天的那塊代碼去了。
  剛開始用起來還是蠻舒服的,但是用久了發(fā)現(xiàn),每次一個新的邏輯都要去實現(xiàn)這個接口,太難受了,突然,想到了java還有匿名類,于是,之后直接用匿名類來實現(xiàn)這個邏輯。代碼如下:

 List<Apple> greenApples = filterApples(inventory, new ApplePredicate() {
            @Override
            public boolean test(Apple apple) {
                return apple.getColor().equals("green");
            }
        });

這樣看起來,的確比之前簡潔多了,不要顯式的去實現(xiàn)一個接口。但是細(xì)細(xì)的觀察了一下,這里面真正有用的代碼就這一行:

return apple.getColor().equals("green");

那么有沒有什么辦法,只給filterApples方法只傳遞這樣真正邏輯性的代碼呢?幸好,java8提供了行為參數(shù)化的支持。好吧,既然都支持了,還等什么,干吧,下面這一行代碼就解決了。

List<Apple> greenApples = filterApples(inventory, (Apple apple) -> apple.getColor().equals("green"));

什么,我沒有看錯吧,這么神?你并沒有看錯,傳遞的參數(shù)叫做lambda表達(dá)式,如果還嫌不夠簡潔,你可以把類型去掉,像這樣:

List<Apple> greenApples = filterApples(inventory, apple -> apple.getColor().equals("green"));

經(jīng)歷了以上幾個階段,我們重構(gòu)了很多次代碼,讓接口能夠適應(yīng)需求的變化,一方面,我們又不想編寫冗余的代碼,通過lambda表達(dá)式來傳遞核心代碼,程序員不在做一些不必要的工作,真的是太好了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,366評論 25 708
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,724評論 19 139

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