1. 程式人生 > >java8學習:通過行為引數化傳遞程式碼

java8學習:通過行為引數化傳遞程式碼

  • 如下一段程式碼請看

    @Test
    public void test() throws Exception { List<Apple> list = new ArrayList<>(); for (Apple apple : list) { if (apple.getWeight() > 1000){ System.out.println("..."); } } }
    • 這段程式碼再簡單不過了,並且完成了該完成的判斷條件,但是如果現在並不是想判斷重量weight了,而是需要判斷color是不是紅色的了,那麼就只能程式碼複製然後改條件了,如下
    @Test
    public void test() throws Exception { List<Apple> list = new ArrayList<>(); for (Apple apple : list) { if ("red".equals(apple.getColor())){ System.out.println("..."); } } }
    • 此時發現,除了更改了if條件,其他地方是沒有動的,但是如果我又需要更改別的條件呢,無奈只好再次變換if條件,針對這一的情況,java8的行為引數化就可以處理頻繁的變更
  • 行為引數化

    • 如上的篩選蘋果顏色的程式碼,這時候我突然想要綠色的或者彩虹色可咋辦難道還要拷貝?
            public void getAppleByColor(List<Apple> apples,String color){ for (Apple apple : apples) { if (color.equals(apple.getColor())){ System.out.println("..."); } } } //getAppleByColor(lists,"red"); //呼叫
    • 上面這段程式碼就解決了一直變更的顏色的問題,任他來的是透明顏色都沒問題,並且呼叫方法時,也可以清晰的看出來我們需要的是什麼蘋果
    • 蘋果大賣錢就多,那麼如果按照重量篩選呢?程式碼已經給出來了,那麼就是開篇的第二段程式碼,仔細想一下雖然解決了我們的問題,但是是不是程式碼重複的太多了,並且這樣的程式設計風格十分不好,違反了DRY(don't repeat yourself),這時候我們就可能想到了進一步的解決辦法來應對重量和顏色的不同選擇,那就是立flag,如下
public void getAppleByColor(List<Apple> apples,String color,Integer weight,boolean isColor){ for (Apple apple : apples) { if ((isColor && color.equals(apple.getColor())) || !isColor && weight > apple.getWeight()){ System.out.println("..."); } } } getAppleByColor(lists,"red",0,true); //呼叫 getAppleByColor(lists,"",123,false); //呼叫
  • 如上,呼叫簡直不能再糟了,如果不讓呼叫者看到方法的方法簽名和解釋,那麼他肯定不會知道true代表啥false代表啥,所以這種方法解決此問題是十分不可取的,那麼我們肯定就需要更好的解決方案
  • 思路:建立一個介面,那麼就有類去實現介面,那麼每個實現類不就代表一種行為嗎?比如這樣改
interface FilterApple{
    boolean filter(Apple apple); } class FilterRedApple implements FilterApple{ @Override public boolean filter(Apple apple) { return "red".equals(apple.getColor()); } } class FilterAppleByWeight implements FilterApple{ @Override public boolean filter(Apple apple) { return apple.getWeight() > 1000; } } public class Java8 { @Test public void test() throws Exception { List<Apple> apples = Arrays.asList(); getAppleByColor(apples,new FilterAppleByWeight()); getAppleByColor(apples,new FilterRedApple()); } public void getAppleByColor(List<Apple> apples,FilterApple filter){ for (Apple apple : apples) { if (filter.filter(apple)) { System.out.println("...."); } } } }
  • 如上程式碼有點長但是十分的簡單,在上面我們可以看到,我們利用了多型的特性來用不同的實現類來實現不同需求的過濾,如果以後把蘋果分男女,那麼我們只需要增加一個FilterAppleByJJ就可以了
  • 引出:如上就是一種行為引數化,讓方法接受多種行為作為引數,並在內部使用,來完成不同的行為
  • 在上面的例子中,唯一重要的也就是filter的實現,但是我們寫的方法只能接受一個FilterApple物件,所以必須把不同的實現程式碼包裹在此物件中。這就好像你借別人錢還要拿紙包起來,不僅老套而且人家關心的只是錢的問題,紙隨便就給扔掉了,在這我們不同實現類中的實現的不同邏輯就是借的錢
    • 但是對於上面的寫法有點太囉裡囉嗦的了,實現一個過濾就要實現一個介面?這時候就應該能想到匿名內部類了把~
    @Test
    public void test() throws Exception { List<Apple> apples = Arrays.asList(); getAppleByColor(apples, new FilterApple() { @Override public boolean filter(Apple apple) { return apple.getWeight() > 1000; } }); } public void getAppleByColor(List<Apple> apples,FilterApple filter){ for (Apple apple : apples) { if (filter.filter(apple)) { System.out.println("...."); } } }
    • 但是匿名內部類還是存在很多的問題,1.就是樣本程式碼太多,2.那麼就是不清楚,比如下面這個,你來看看輸出什麼,答案在最下面
    public class Java8 {
        private final int value = 4; public void doIt(){ int value = 6; Runnable runnable = new Runnable() { public final int value = 5; @Override public void run() { int value = 10; System.out.println(this.value); } }; runnable.run(); } public static void main(String[] args) { new Java8().doIt(); } }
    • 匿名內部類的弊端:在只需要傳遞一段簡單的程式碼時,還是需要建立一個物件,明確的實現一個方法來定義一個新的行為
    • 上面的問題來充實Lambda表示式解決

      @Test
      public void test() throws Exception { List<Apple> apples = Arrays.asList(); getAppleByColor(apples,(apple) -> apple.getWeight() > 1000); } public void getAppleByColor(List<Apple> apples,FilterApple filter){ for (Apple apple : apples) { if (filter.filter(apple)) { System.out.println("...."); } } }
      • 爽的一批,對於lambda以後會繼續說的
      • 但是還有個問題,這個只能是過濾Apple把,如果我還有西瓜之類的呢,那麼程式碼就可以引入泛型T
    interface Filter<T>{
        boolean filter(T t); } public class Java8 { @Test public void test() throws Exception { List<Apple> apples = Arrays.asList(); getAppleByColor(apples,apple -> apple.getWeight() > 1000); } public <T> void getAppleByColor(List<T> ts,Filter<T> filter){ for (T t : ts) { if (filter.filter(t)){ System.out.println("..."); } } } }
    • 這時候就想過濾什麼就過濾什麼了
    Comparator排序
    @Test
    public void test() throws Exception { List<Apple> apples = Arrays.asList(); apples.sort(Comparator.comparing(Apple::getWeight)); } or @Test public void test() throws Exception { List<Apple> apples = Arrays.asList(); apples.sort((a1,a2) -> a1.getWeight().compareTo(a2.getWeight())); }
    • Runnable
    @Test
    public void test() throws Exception { Runnable runnable = ()->{ System.out.println("run"); }; runnable.run(); }
    • 好了上面是兩個例子僅供參考