Java8筆記4

                         使用 Lambda 重構面向對象的設計模式Ⅱ

 

1.觀察者模式:

觀察者模式是一種比較常見的方案,某些事件發生時(比如狀態轉變),如果一個對象(通 常我們稱之爲主題)需要自動地通知其他多個對象(稱爲觀察者),就會採用該方案。

 

首先,你需要一個觀察者接口,它將不同的觀察者聚合在一起。它僅有一個名爲notify的 方法,一旦接收到一條新的新聞,該方法就會被調用:
interface Observer { 
 void notify(String tweet); 
}
現在,你可以聲明不同的觀察者(比如,這裏是三家不同的報紙機構),依據新聞中不同的 關鍵字分別定義不同的行爲:
class NYTimes implements Observer{ 
 public void notify(String tweet) { 
 if(tweet != null && tweet.contains("money")){ 
 System.out.println("Breaking news in NY! " + tweet); 
 } 
 } 
} 
class Guardian implements Observer{ 
 public void notify(String tweet) { 
 if(tweet != null && tweet.contains("queen")){ 
 System.out.println("Yet another news in London... " + tweet); 
 } 
 } 
} 
class LeMonde implements Observer{ 
 public void notify(String tweet) { 
 if(tweet != null && tweet.contains("wine")){ 
 System.out.println("Today cheese, wine and news! " + tweet); 
 } 
 } 
}

主題接口:

interface Subject{ 
 void registerObserver(Observer o); 
 void notifyObservers(String tweet); 
}
       Subject使用registerObserver方法可以註冊一個新的觀察者,使用notifyObservers 方法通知它的觀察者一個新聞的到來。讓我們更進一步,實現Feed類:
class Feed implements Subject{ 
 private final List<Observer> observers = new ArrayList<>(); 
 public void registerObserver(Observer o) { 
 this.observers.add(o); 
 } 
 public void notifyObservers(String tweet) { 
 observers.forEach(o -> o.notify(tweet)); 
 } 
}
這是一個非常直觀的實現:Feed類在內部維護了一個觀察者列表,一條新聞到達時,它就 進行通知。
Feed f = new Feed(); 
f.registerObserver(new NYTimes()); 
f.registerObserver(new Guardian()); 
f.registerObserver(new LeMonde()); 
f.notifyObservers("today is 2020/5/14, plt had dead out");
使用Lambda表達式
       你可能會疑惑Lambda表達式在觀察者設計模式中如何發揮它的作用。不知道你有沒有注意
到,Observer接口的所有實現類都提供了一個方法:notify。新聞到達時,它們都只是對同一
段代碼封裝執行。Lambda表達式的設計初衷就是要消除這樣的僵化代碼。使用Lambda表達式後,
你無需顯式地實例化三個觀察者對象,直接傳遞Lambda表達式表示需要執行的行爲即可:
f.registerObserver((String tweet) -> { 
 if(tweet != null && tweet.contains("money")){ 
 System.out.println("Breaking news in NY! " + tweet); 
 } 
}); 
f.registerObserver((String tweet) -> { 
 if(tweet != null && tweet.contains("queen")){ 
 System.out.println("Yet another news in London... " + tweet); 
 } 
});
        那麼,是否我們隨時隨地都可以使用Lambda表達式呢?答案是否定的!我們前文介紹的例
子中,Lambda適配得很好,那是因爲需要執行的動作都很簡單,因此才能很方便地消除僵化代
碼。但是,觀察者的邏輯有可能十分複雜,它們可能還持有狀態,抑或定義了多個方法,諸如此
類。在這些情形下,你還是應該繼續使用類的方式。
 
2.責任鏈模式:
       責任鏈模式是一種創建處理對象序列(比如操作序列)的通用方案。一個處理對象可能需要
在完成一些工作之後,將結果傳遞給另一個對象,這個對象接着做一些工作,再轉交給下一個處
理對象,以此類推。
      通常,這種模式是通過定義一個代表處理對象的抽象類來實現的,在抽象類中會定義一個字
段來記錄後續對象。一旦對象完成它的工作,處理對象就會將它的工作轉交給它的後繼。代碼中,
這段邏輯看起來是下面這樣:
public abstract class ProcessingObject<T> { 
 protected ProcessingObject<T> successor; 
 public void setSuccessor(ProcessingObject<T> successor){ 
 this.successor = successor;
} 
 public T handle(T input){ 
 T r = handleWork(input); 
 if(successor != null){ 
 return successor.handle(r); 
 } 
 return r; 
 } 
 abstract protected T handleWork(T input); 
}

 

其實這就是模板方法設計模式。handle方法提供瞭如何進行
工作處理的框架。不同的處理對象可以通過繼承ProcessingObject類,提供handleWork方法
來進行創建。
public class HeaderTextProcessing extends ProcessingObject<String> { 
 public String handleWork(String text){ 
 return "From a, b and c: " + text; 
 } 
} 
public class SpellCheckerProcessing extends ProcessingObject<String> { 
 public String handleWork(String text){ 
 return text.replaceAll("abc", "bcd"); 
 } 
}
現在你就可以將這兩個處理對象結合起來,構造一個操作序列
 
ProcessingObject<String> p2 = new SpellCheckerProcessing(); 
p1.setSuccessor(p2);
String result = p1.handle("Aren't abc really sexy?!!"); 
System.out.println(result);
輸出:“From a, b and c:  Aren't bcd really sexy?!!”
 
使用Lambda表達式
UnaryOperator<String> headerProcessing = 
 (String text) -> "From a, b and c: " + text;
UnaryOperator<String> spellCheckerProcessing = 
 (String text) -> text.replaceAll("abc", "bcd"); 
Function<String, String> pipeline = 
 headerProcessing.andThen(spellCheckerProcessing); 
String result = pipeline.apply("Aren't abc really sexy?!!");

 

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章