Java 8 - 行爲參數化

前言:java

如下內容來源於java8實戰一書,我將裏面學習的內容作一個整理,方便忙碌的小夥伴快速入門實戰java8app

正文:ide

假設一個果農收穫了一園的蘋果,他須要你根據他的條件篩選出滿意的蘋果學習

首先咱們新建一個Apple類spa

public class Apple {
    
    /**
     * 重量
     */
    private Integer weight;
    
    /**
     * 顏色
     */
    private String color;
   
   getter();
   setter();
   toString();
   ...
}

他說:我須要挑出紅蘋果code

public void filterRedApple(List<Apple> appleList){ for(Apple apple : appleList){ if("red".equals(apple)){ System.out.println("紅蘋果"); } } } 

他說:我要挑出綠蘋果對象

轉念一想,把顏色做爲參數吧blog

    public void filterGreenApple(List<Apple> appleList , String color) {
        for (Apple apple : appleList) {
            if (color.equals(apple)) {
                System.out.println("綠蘋果");
            }
        }
    }

他說:我須要挑出150g的蘋果接口

    public void filterWeightApple(List<Apple> appleList,Integer weight) {
        for (Apple apple : appleList) {
            if (apple.getWeight() > weight) {
                System.out.println("重量大於150g的蘋果");
            }
        }
    }

他說:我要挑出100g以上的紅蘋果get

    public void filterAppleByWeightAndColor(List<Apple> appleList,String color,Integer weight){
        for (Apple apple : appleList) {
            if (apple.getWeight() > weight && color.equals(apple.getColor())) {
                System.out.println("重量大於100g的紅蘋果");
            }
        }
    }

面對無止境的需求變化,咱們須要不斷的適應

讓咱們來看看如何改進

新建一個蘋果篩選接口

public interface ApplePredicate {
    
    /**
     * 篩選蘋果
     */
    boolean test(Apple apple);
    
}

而後咱們分別實現篩選方法

根據顏色篩選

public class FilterRedApple implements ApplePredicate {

    @Override
    public boolean test(Apple apple) {
        return "red".equals(apple.getColor()) ? true : false;
    }

}

根據重量篩選

public class FilterWeightApple implements ApplePredicate {

    @Override
    public boolean test(Apple apple) {
        return apple.getColor() > 100 ? true : false;
    }

}

根據顏色和重量篩選

public class FilterAppleByColorAndWeight implements ApplePredicate {

    @Override
    public boolean test(Apple apple) {
        return "red".equals(apple.getColor()) && apple.getWeight > 100 ? true : false;
    }

}

好比他想要紅蘋果

咱們這樣來給他實現

    public static void filterApple(List<Apple> appleList , ApplePredicate p) {
        for (Apple apple : appleList) {
            if (p.test(apple)) {
                System.out.println("這是你要的蘋果" + apple.toString());
            }
        }
    }

咱們調用的時候,傳入它的實現類就好了

    public static void main(String[] args) {
        filterApple(appleList, new FilterRedApple());
        filterApple(appleList, new FilterWeightApple());
    }

咱們來看看如今的方法和原先的方法的區別:

原先的方法是每提出一個需求咱們就新寫一個方法來實現它,這樣代碼會顯得很是臃腫冗餘,由於他們實際上是作的同一件事:篩選想要的蘋果,僅僅只是條件不一樣

咱們改進後的方法是:寫一個篩選接口,而後分別實現這個接口,好比你想要紅蘋果就寫個曬選紅蘋果的實現,想要大的蘋果就再寫一個新的實現

這看起來有點像策略模式

好的。咱們已經完成了一件很是酷的事:fliterApple方法的行爲取決於咱們經過ApplePredicate對象傳遞的代碼,這個就是行爲參數化,它能夠幫助咱們編寫靈活的API

如今,可能有同窗會問我,每次新的需求都寫一個新的實現類,會不會太麻煩了,咱們能夠用匿名類來實現啊

確實,咱們能夠用匿名類來實現

    public static void main(String[] args) {       
     
    filterApple(appleList,
new ApplePredicate() {
       @Override
public boolean test(Apple apple) { return "red".equal(apple.getColor) ? true : false; } });
}

雖然匿名類在必定程度上改善了爲一個接口寫好幾個實現類的囉嗦問題,但它仍是要建立一個對象明確的實現新的方法來定義一個新的行爲

因此,相較之下我更傾向於使用行爲參數化的形式

概念:

行爲參數化:一個方法接受多個不一樣的行爲做爲參數,並在內部使用他們,完成不一樣行爲的能力

行爲參數化可讓代碼更好的適應不斷變化的需求,減輕將來的工做量

傳遞代碼:將新行爲做爲參數傳遞給方法

相關文章
相關標籤/搜索