使用Lambda的装饰设计模式
隨著Java中lambda的出現,我們現在有了一個新工具,可以更好地設計我們的代碼。 當然,第一步是使用流,方法引用和Java 8中引入的其他簡潔功能。
展望未來,我認為下一步是重新訪問完善的設計模式,并通過功能性編程視角進行了解。 為此,我將采用Decorator模式,并使用lambdas實現它。
我們將以裝飾器模式的簡單且美味的示例為例:在披薩中添加澆頭。 這是GoF建議的標準實現:
首先,我們具有定義組件的接口:
public interface Pizza {String bakePizza(); }我們有一個具體的組成部分:
public class BasicPizza implements Pizza {@Overridepublic String bakePizza() {return "Basic Pizza";} }我們決定必須以不同的方式裝飾組件。 我們選擇裝飾器模式。 這是抽象裝飾器:
public abstract class PizzaDecorator implements Pizza {private final Pizza pizza;protected PizzaDecorator(Pizza pizza) {this.pizza = pizza;}@Overridepublic String bakePizza() {return pizza.bakePizza();} }我們為組件提供了一些具體的裝飾器:
public class ChickenTikkaPizza extends PizzaDecorator {protected ChickenTikkaPizza(Pizza pizza) {super(pizza);}@Overridepublic String bakePizza() {return super.bakePizza() + " with chicken topping";} }public class ProsciuttoPizza extends PizzaDecorator {protected ProsciuttoPizza(Pizza pizza) {super(pizza);}@Overridepublic String bakePizza() {return super.bakePizza() + " with prosciutto";} }這是使用新結構的方式:
Pizza pizza = new ChickenTikkaPizza(new BasicPizza()); String finishedPizza = pizza.bakePizza(); //Basic Pizza with chicken toppingpizza = new ChickenTikkaPizza(new ProsciuttoPizza(new BasicPizza())); finishedPizza = pizza.bakePizza(); //Basic Pizza with prosciutto with chicken topping我們可以看到這會變得非常混亂,如果考慮如何處理Java中的緩沖讀取器,它的確會變得非常混亂:
new DataInputStream(new BufferedInputStream(new FileInputStream(new File("myfile.txt"))))當然,您可以將其拆分為多行,但這不會解決混亂問題,只會分散它。 現在讓我們看看如何使用lambda來做同樣的事情。 我們從相同的基本組件對象開始:
public interface Pizza {String bakePizza(); }public class BasicPizza implements Pizza {@Overridepublic String bakePizza() {return "Basic Pizza";} }但是現在,我們不再聲明一個抽象類來提供裝飾的模板,而是創建一個裝飾器,該裝飾器要求用戶提供裝飾組件的功能。
public class PizzaDecorator {private final Function<Pizza, Pizza> toppings;private PizzaDecorator(Function<Pizza, Pizza>... desiredToppings) {this.toppings = Stream.of(desiredToppings).reduce(Function.identity(), Function::andThen);}public static String bakePizza(Pizza pizza, Function<Pizza, Pizza>... desiredToppings) {return new PizzaDecorator(desiredToppings).bakePizza(pizza);}private String bakePizza(Pizza pizza) {return this.toppings.apply(pizza).bakePizza(); }}這條線構成了要應用的裝飾鏈:
Stream.of(desiredToppings).reduce(identity(), Function::andThen);這行代碼將接受您的裝飾(屬于Function類型),并使用andThen鏈接它們。 這和
(currentToppings, nextTopping) -> currentToppings.andThen(nextTopping)并確保隨后按您提供的順序調用這些函數。 還將Function.identity()轉換為elem-> elem lambda表達式。 好的,現在我們在哪里定義裝飾? 您可以在PizzaDecorator甚至在界面中將它們添加為靜態方法:
public interface Pizza {String bakePizza();static Pizza withChickenTikka(Pizza pizza) {return new Pizza() {@Overridepublic String bakePizza() {return pizza.bakePizza() + " with chicken";}};}static Pizza withProsciutto(Pizza pizza) {return new Pizza() {@Overridepublic String bakePizza() {return pizza.bakePizza() + " with prosciutto";}};} }現在,這就是這種模式的使用方式:
String finishedPizza = PizzaDecorator.bakePizza(new BasicPizza(),Pizza::withChickenTikka, Pizza::withProsciutto);//And if you static import PizzaDecorator.bakePizza:String finishedPizza = bakePizza(new BasicPizza(),Pizza::withChickenTikka, Pizza::withProsciutto);如您所見,代碼變得更加清晰和簡潔,我們沒有使用繼承來構建我們的裝飾器。
這只是可以使用lambda改進的眾多設計模式之一。 還有更多功能可用來改善其余功能,例如使用部分應用程序(循環)來實現適配器模式。
希望我能引起您考慮對您的開發風格采用功能更強大的編程方法的想法。
參考書目
裝飾器示例的靈感來自“ 四人幫” –“用裝飾器設計模式進行裝飾”一文。
重構方法是受以下Devoxx 2015演講的啟發(我建議在觀看這些演講時將其視為主題): Remi Forax重新加載的 設計模式,Venkat Subramaniam的Lambda表達形式的設計模式
翻譯自: https://www.javacodegeeks.com/2015/12/decorator-design-pattern-using-lambdas.html
總結
以上是生活随笔為你收集整理的使用Lambda的装饰设计模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微信支付客服电话人工服务几点上班?
- 下一篇: 现货黄金有主力主控吗?