设计模式的Java 8 Lambda表达式–装饰器设计模式
Decorator模式(也稱為Wrapper )允許將行為靜態或動態地添加到單個對象,而不會影響同一類中其他對象的行為。 可以將其視為子類的替代方法。 我們知道子類在編譯時會增加行為,并且更改會影響原始類的所有實例。 另一方面,裝飾可以在運行時為選擇性對象提供新的行為。
裝飾器與其裝飾的組件的接口一致,從而對組件的客戶端透明。 裝飾器將請求轉發到組件,并且可以在轉發之前或之后執行其他操作。 透明度允許裝飾器遞歸嵌套,從而允許無限數量的添加職責。 裝飾器模式的主要參與者如下所示:
- 組件 –指定可以動態添加職責的對象的接口。
- ConcreteComponent –定義可以添加其他職責的對象
- 裝飾器 –保留對Component對象的引用并符合Component的接口。 它包含要裝飾的Component對象。
- ConcreteDecorator –向組件添加責任。
現在,讓我們來看一個裝飾器模式的具體示例,并看一下如何使用lambda表達式對其進行轉換。 假設我們有不同類型的書籍,而這些書籍的封面或類別可能不同。 我們可以選擇任何書籍,并通過繼承來指定類別或語言。 可以將書籍抽象為一類。 之后,任何其他類都可以擴展Book類并覆蓋cover或category的方法。 但這不是一種有效的方法。 在這種方法下,子類可能具有從超類擴展過來的不必要的方法。 同樣,如果我們必須添加更多的屬性或特性,則父類也會有所變化。 更改類的實現應該是最后的選擇。
讓我們通過使用裝飾器模式來采取最佳方法。 我們將使用基本方法為Book創建一個接口:
public interface Book {public String describe();}BasicBook類可以實現此接口以提供最小的抽象:
public class BasicBook implements Book {@Overridepublic String describe() {return "Book";}}接下來,讓我們定義抽象類BookDecorator ,它將充當Decorator:
abstract class BookDecorator implements Book {protected Book book;BookDecorator(Book book) {this.book = book;}@Overridepublic String describe() {return book.describe();} }BookDecorator類符合Book接口,并且還存儲對Book接口的引用。 如果要將類別作為屬性添加到Book接口,則可以使用實現BookDecorator接口的具體類。 對于小說類別,我們可以使用以下裝飾器:
public class FictionBookDecorator extends BookDecorator {FictionBookDecorator(Book book) {super(book);}@Overridepublic String describe() {return ("Fiction " + super.describe());} }您可以看到FictionBookDecorator在原始操作(即描述)中添加了圖書的類別。 同樣,如果要指定“科學”類別,則可以具有相應的“ ScienceBookDecorator” :
public class ScienceBookDecorator extends BookDecorator {ScienceBookDecorator(Book book) {super(book);}@Overridepublic String describe() {return ("Science " + super.describe());} }ScienceBookDecorator還會在原始操作中添加書籍的類別。 也可以有另一套裝飾器,指示書籍的封面類型。 我們可以用SoftCoverDecorator來描述這本書有一個軟封面。
public class SoftCoverDecorator extends BookDecorator {SoftCoverDecorator(Book book) {super(book);}@Overridepublic String describe() { return (super.describe() + " with Soft Cover");} }我們還可以使用HardCoverDecorator來描述這本書的精裝本。
public class HardCoverDecorator extends BookDecorator {HardCoverDecorator(Book book) {super(book);}@Overridepublic String describe() { return (super.describe() + " with Hard Cover");} }現在,讓我們結合定義的所有類和接口,以利用Decorator模式的強大功能。 僅查看所有這些類的一個示例相互作用:
import java.util.List; import java.util.ArrayList;public class BookDescriptionMain {public static void main(String [] args) {BasicBook book = new BasicBook();//Specify book as Fiction categoryFictionBookDecorator fictionBook = new FictionBookDecorator(book);//Specify that the book has a hard coverHardCoverDecorator hardCoverBook = new HardCoverDecorator(book);//What if we want to specify both the category and cover type togetherHardCoverDecorator hardCoverFictionBook = new HardCoverDecorator(fictionBook); //Specify book as Science categoryScienceBookDecorator scienceBook = new ScienceBookDecorator(book);//What if we want to specify both the category and cover type togetherHardCoverDecorator hardCoverScienceBook = new HardCoverDecorator(scienceBook); //Add all the decorated book items in a listList<Book> bookList = new ArrayList<Book>() {{add(book);add(fictionBook);add(hardCoverBook);add(hardCoverFictionBook);add(scienceBook);add(hardCoverScienceBook);}};//Traverse the list to access all the book itemsfor(Book b: bookList) {System.out.println(b.describe());} } }運行此命令可獲得以下輸出:
BookFiction BookBook with Hard CoverFiction Book with Hard CoverScience BookScience Book with Hard Cover它清楚地說明了如何將不同的屬性添加到任何預定義的類/對象。 同樣,可以組合多個屬性。 我試圖將所有裝飾的書本組合在一個列表中,然后通過遍歷該列表來訪問它們。
到目前為止,我們所看到的只是標準的裝飾器模式,而且已經存在了很長時間。 在這些時候,當函數式編程成為新的流行語時,人們可能會思考Java中對lambda表達式的支持是否會有所不同。 實際上,由于修飾后的接口就像一個函數接口,因此我們可以使用Java中的lambda表達式進行哈希處理。 讓我們看一下代碼的樣子:
import java.util.List; import java.util.ArrayList;public class BookDescriptionMainWithLambda {public static void main(String [] args) {BasicBook book = new BasicBook();//Specify book as Fiction category using Lambda expressionBook fictionBook = () -> "Fiction " + book.describe();//Specify that the book has a hard cover using Lambda expressionBook hardCoverBook = () -> book.describe() + " with Hard Cover";//What if we want to specify both the category and cover type togetherBook hardCoverFictionBook = () -> fictionBook.describe() + " with Hard Cover"; //Specify book as Science category using Lambda expressionBook scienceBook = () -> "Science " + book.describe();//What if we want to specify both the category and cover type togetherBook hardCoverScienceBook = () -> fictionBook.describe() + " with Hard Cover"; List<Book> bookList = new ArrayList<Book>() {{add(book);add(fictionBook);add(hardCoverBook);add(hardCoverFictionBook);add(scienceBook);add(hardCoverScienceBook);}};bookList.forEach(b -> System.out.println(b.describe()));} }運行此命令可獲得類似的輸出:
BookFiction BookBook with Hard CoverFiction Book with Hard CoverScience BookFiction Book with Hard Cover我們可以看到,使用lambda表達式會使裝飾器的其他類變得多余。 您不需要其他課程; 只需使用lambda表達式指定其他行為。 但是,支持再次找到裝飾器以供重新使用。 如果您有具體的裝飾器類,則下次也可以重用它。
- 可以從我的github存儲庫訪問所有代碼片段
翻譯自: https://www.javacodegeeks.com/2015/12/java-8-lambda-expression-design-patterns-decorator-design-pattern.html
總結
以上是生活随笔為你收集整理的设计模式的Java 8 Lambda表达式–装饰器设计模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 消息称Meta计划明年初开发全新的大型语
- 下一篇: 分析师:台积电 8 月营收增长 6.2%