# Java的方法鏈 Java的方法鏈(method chain) 方法鏈(method chain)顧名思義,就是把一些方法串接起來,讓前一個方法回傳「處理過後的物件」,並且讓它再去執行下一個方法。 舉個例子,假設我們宣告一個「廚師」類別,並且將它實體化,建立一個叫做「小當家」的具體物件,小當家可以使用「收集食材()、加水()、大火快炒()、加米酒()、瀝乾()、加上蔥花()」這些方法來做菜,但如果我們這樣寫: 小當家 . 收集食材(); 小當家 . 加水(); 小當家 . 大火快炒(); 小當家 . 加米酒(); 小當家 . 瀝乾(); 小當家 . 加上蔥花(); 這樣寫的話,代表小當家「各別」執行這些方法,這6個方法的回傳值彼此之間是互相獨立的,所以會各自得到6個方法的回傳值。不過,很明顯現在這些方法是互相依附而且有順序性的,這樣寫的話等於是「分別」做這6種行為,所以我們並無法順利把這盤菜做出來,只會得到沒有處理過的食材、一杯水、大火快炒的空鍋子、撒在外面的米酒 … 等。 要把這盤菜做出來,這6個方法一定要串成一條「鏈子」,也就是說從第一步收集食材之後,就要依序完成其他步驟,並且要讓前一個方法回傳「處理過後的物件」,並且讓它再去執行下一個方法,這就輪到方法鏈出場了。 為了實現這個想法,我們一開始會想到要這麼做: 小當家 . 收集食材(); 食材 . 加水(); 加水後的食材 . 大火快炒(); 炒熟的食材 . 加米酒(); 加米酒後的食材 . 瀝乾(); 瀝乾後的食材 . 加上蔥花(); 這樣寫並沒有錯,但等於說現在我們除了「小當家」這個物件之外,還要另外建立其他5個物件!這樣不是很累嗎 … 而且還多了一大堆過渡性質的物件,讓程式碼變得又臭又長,也增加出錯的機率。 為了改善這個問題,專家們想到一個解決方案,也就是執行完一個方法後,把該方法「回傳值的型態」設定為參考(reference)型態,也就是回傳處理過後的「物件」,再用這個物件去執行下一個方法。 虛擬碼如下: 小當家 . 收集食材();  回傳食材 食材 . 加水();  回傳加水後的食材 加水後的食材 . 大火快炒();  回傳炒熟的食材 炒熟的食材 . 加米酒();  回傳加米酒後的食材 加米酒後的食材 . 瀝乾();  回傳瀝乾後的食材 瀝乾後的食材 . 加上蔥花(); 有了這個觀念後,我們就可以只用一列,就把程式碼寫出來了: 小當家 . 收集食材() . 加水(). 大火快炒(). 加米酒(). 瀝乾(). 加上蔥花(); 這樣一來,不但可以順利完成目的,程式碼變得精簡,也更好理解。我們把以上的虛擬碼,寫成更接近Java語言的形式: object2 = object1.method1(); // 等號右邊的物件方法執行完後,回傳一個物件,稱為object2 object3 = object2.method2(); // 把object2執行完方法之後的物件,稱為object3 object3.method3(); // 執行object3的方法。為了簡化問題,沒有object4了 因為這種寫法沒有使用方法鏈,所以我們需要object2這個作為「過渡」的物件。 以上三列程式碼若使用方法鏈,一列就寫完了,也更加易懂,如下: object1.method1().method2().method3(); 實際上,要避免使用到object2這個過渡物件,我們還需要加上「return this」這一列。不懂沒關係,我們以一個實際的例子來看看方法鏈要怎麼使用: // 宣告Person類別 class Person{ private String name; // Person類別的屬性 private int age; // 定義setName方法,輸入值是字串,回傳值是Person型態的資料 public Person setName(String name){ this . name = name; return this; } // 回傳這個方法執行完之後的物件的「參考」 // 定義setAge方法,輸入值是整數,回傳值是Person型態的資料 public Person setAge(int age){ this . age = age; return this; } // 回傳這個方法執行完之後的物件的「參考」 // 定義introduce()方法,不需要輸入值,也不需要回傳資料(void)。 public void introduce(){ System.out.println(”Hello , my name is” + name + “and I am” + age + “years old.”); } // 以下是程式的進入點 public static void main(String[ ] args) { Person man1 = new Person(); // 實體化,建立man1物件 man1 . setName(”John”) . setAge(24) . introduce(); } // 以方法鏈執行物件的方法 } 編譯並執行此程式,輸出為:「Hello, my name is John and I am 24 years old.」。 重點是,對於要做method chain的方法,它的回傳值型態要為類別型態,此例中即為Person型態,而且對於要做method chain的方法的{ }區塊內,最後一列要寫上: return this ; 代表回傳這個方法執行完之後的資料的「參考」(reference),以便我們將運算過後的資料作為一個物件,讓該物件繼續去執行下一個方法,就像剛才我們舉的小當家做菜的例子一樣。若是少寫return this,方法鏈便不能被正確的執行下去,除非你不需要使用方法鏈。 至於方法鏈的缺點嘛 … 可能對於初學者而言比較困難一點,還有除錯較為複雜,但熟練之後就沒有這些問題了。