Lambda 重構面向對象的設計模式
策略模式
策略模式包含三部分內容
一個代表某個算法的接口(它是策略模式的接口)。
一個或多個該接口的具體實現,它們代表了算法的多種實現(比如,實體類ConcreteStrategyA或者ConcreteStrategyB)。
一個或多個使用策略對象的客戶
public interface ValidationStrategy { boolean execute(String s);
}public class IsAllLowerCase implements ValidationStrategy { public boolean execute(String s){ return s.matches("[a-z]+"); }
}
public class IsNumeric implements ValidationStrategy { public boolean execute(String s){ return s.matches("\\d+"); }
}public class Validator{ private final ValidationStrategy strategy; public Validator(ValidationStrategy v){ this.strategy = v; } public boolean validate(String s){ return strategy.execute(s); }
}
Validator numericValidator = new Validator(new IsNumeric());
boolean b1 = numericValidator.validate("aaaa");
Validator lowerCaseValidator = new Validator(new IsAllLowerCase ());
boolean b2 = lowerCaseValidator.validate("bbbb");
Validator numericValidator = new Validator((String s) -> s.matches("[a-z]+"));
boolean b1 = numericValidator.validate("aaaa");
Validator lowerCaseValidator = new Validator((String s) -> s.matches("\\d+"));
boolean b2 = lowerCaseValidator.validate("bbbb");
Lambda表達式避免了采用策略設計模式時僵化的模板代碼。如果你仔細分 析一下個中緣由,可能會發現,Lambda表達式實際已經對部分代碼(或策略)進行了封裝,而 這就是創建策略設計模式的初衷。因此,我們強烈建議對類似的問題,你應該盡量使用Lambda 表達式來解決
模板方法
讓我們從一個例子著手,看看這個模式是如何工作的。假設你需要編寫一個簡單的在線銀行 應用。通常,用戶需要輸入一個用戶賬戶,之后應用才能從銀行的數據庫中得到用戶的詳細信息, 最終完成一些讓用戶滿意的操作。不同分行的在線銀行應用讓客戶滿意的方式可能還略有不同, 比如給客戶的賬戶發放紅利,或者僅僅是少發送一些推廣文件。你可能通過下面的抽象類方式來 實現在線銀行應用
abstract class OnlineBanking { public void processCustomer(int id){ Customer c = Database.getCustomerWithId(id); makeCustomerHappy(c); }abstract void makeCustomerHappy(Customer c);
}
使用Lambda表達式
public void processCustomer(int id, Consumer<Customer> makeCustomerHappy){ Customer c = Database.getCustomerWithId(id); makeCustomerHappy.accept(c);
} new OnlineBankingLambda().processCustomer(1337, (Customer c) -> System.out.println("Hello " + c.getName());
觀察者模式
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);
} 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 f = new Feed();
f.registerObserver(new NYTimes());
f.registerObserver(new Guardian());
f.registerObserver(new LeMonde());
f.notifyObservers("The queen said her favourite book is Java 8 in Action!");
使用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適配得很好,那是因為需要執行的動作都很簡單,因此才能很方便地消除僵化代 碼。但是,觀察者的邏輯有可能十分復雜,它們可能還持有狀態,抑或定義了多個方法,諸如此 類。在這些情形下,你還是應該繼續使用類的方式
責任鏈模式
通常,這種模式是通過定義一個代表處理對象的抽象類來實現的,在抽象類中會定義一個字 段來記錄后續對象。一旦對象完成它的工作,處理對象就會將它的工作轉交給它的后繼。代碼中, 這段邏輯看起來是下面這樣
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);
} public class HeaderTextProcessing extends ProcessingObject<String> { public String handleWork(String text){ return "From Raoul, Mario and Alan: " + text; }
}
public class SpellCheckerProcessing extends ProcessingObject<String> { public String handleWork(String text){ return text.replaceAll("labda", "lambda"); }
} ProcessingObject<String> p1 = new HeaderTextProcessing();
ProcessingObject<String> p2 = new SpellCheckerProcessing();
p1.setSuccessor(p2);
String result = p1.handle("Aren't labdas really sexy?!!");
System.out.println(result);
使用Lambda表達式
UnaryOperator<String> headerProcessing = (String text) -> "From Raoul, Mario and Alan: " + text;
UnaryOperator<String> spellCheckerProcessing = (String text) -> text.replaceAll("labda", "lambda");
Function<String, String> pipeline = headerProcessing.andThen(spellCheckerProcessing);
String result = pipeline.apply("Aren't labdas really sexy?!!")
工廠模式
public class ProductFactory { public static Product createProduct(String name){ switch(name){ case "loan": return new Loan(); case "stock": return new Stock(); case "bond": return new Bond(); default: throw new RuntimeException("No such product " + name); } }
}
Product p = ProductFactory.createProduct("loan");
使用Lambda表達式
final static Map<String, Supplier<Product>> map = new HashMap<>();
static { map.put("loan", Loan::new); map.put("stock", Stock::new); map.put("bond", Bond::new);
} public static Product createProduct(String name){ Supplier<Product> p = map.get(name); if(p != null) return p.get(); throw new IllegalArgumentException("No such product " + name);
}