行為參數化

假設有如下業務:有一堆有顏色和重量的蘋果,我需要通過顏色和重量取出相應蘋果
定義蘋果

    public class Apple {
        private int weight = 0;
        private String color = "";

        public Apple(int weight, String color){
            this.weight = weight;
            this.color = color;
        }

        public Integer getWeight() {
            return weight;
        }

        public void setWeight(Integer weight) {
            this.weight = weight;
        }

        public String getColor() {
            return color;
        }

        public void setColor(String color) {
            this.color = color;
        }

        public String toString() {
            return "Apple{" +
                    "color='" + color + '\'' +
                    ", weight=" + weight +
                    '}';
        }
    }

假設

inventory = Arrays.asList(new Apple(80,"green"), new Apple(155, "green"), new Apple(120, "red"));

解決方案1:

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

這是最常見的方法。但是這樣的結構很難復用。比如我顏色不確定呢?

解決方案2:

        List<Apple> result = new ArrayList<>();
        for(Apple apple: inventory){
            if(apple.getColor().equals(color)){
                result.add(apple);
            }
        }

如果我需要100g以上的且紅色的蘋果我就需要

        List<Apple> result = new ArrayList<>();
        for(Apple apple: inventory){
            if(apple.getColor().equals(color) 
                            && apple.getWeight() > weight){
                result.add(apple);
            }
        }

如果我需要100g以上或者紅色的蘋果

        List<Apple> result = new ArrayList<>();
        for(Apple apple: inventory){
            if(apple.getColor().equals(color) 
                            || apple.getWeight() > weight){
                result.add(apple);
            }
        }

是不是變得沒完沒了了?
解決方案3:

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;
    }
    interface ApplePredicate{
        boolean test(Apple a);
    }
     class AppleWeightPredicate implements ApplePredicate{
        public boolean test(Apple apple){
            return apple.getWeight() > 150;
        }
    }
     class AppleColorPredicate implements ApplePredicate{
        public boolean test(Apple apple){
            return "green".equals(apple.getColor());
        }
    }

     class AppleRedAndHeavyPredicate implements ApplePredicate{
        public boolean test(Apple apple){
            return "red".equals(apple.getColor())
                    && apple.getWeight() > 150;
        }
    }
List<Apple> greenApples2 = filterApples(inventory, new AppleColorPredicate());

這種方法和合適。不過如果規則也是不確定的呢?

解決方案4:

        List<Apple> redApples2 = filterApples(inventory, new ApplePredicate() {
            public boolean test(Apple a){
                return a.getColor().equals("red");
            }
        });

Good!這樣就能做到定制化了。不過通過lambda寫起來更加優美

解決方案5:

        List<Apple> redApples2 = filterApples(inventory, (Apple a)-> a.getColor().equals("red"));
        

如果我們要推廣。不只是蘋果而是所有的判斷規則?

解決方案6:

    interface Predicate<T>{
        boolean test(T t);
    }

    public static <T> List<T> filter(List<T> inventory, Predicate<T> p){
        List<T> result = new ArrayList<>();
        for(T apple : inventory){
            if(p.test(apple)){
                result.add(apple);
            }
        }
        return result;
    }
        
List<Apple> redApples2 = filter(inventory, (Apple a)-> a.getColor().equals("red"));

其實java 8 的思路也是這樣的
解決方案7:

        List<Apple> redApples2 = inventory
                .stream()
                .filter((Apple a)-> a.getColor().equals("red"))
                .collect(Collectors.toList());
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容