<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                # Java 中的裝飾器設計模式 > 原文: [https://howtodoinjava.com/design-patterns/structural/decorator-design-pattern/](https://howtodoinjava.com/design-patterns/structural/decorator-design-pattern/) 在軟件工程中,**裝飾器設計模式**用于向類的特定實例添加其他功能或行為,而不會修改同一類的其他實例。 裝飾器提供了子類別的靈活替代方案,以擴展功能。 請注意,以上描述暗示裝飾對象會更改其行為,但不會更改其接口。 理解這種模式非常重要,因為一旦您了解了裝飾技術,就可以賦予您(或其他人)對象新的職責,而無需對基礎類進行任何代碼更改。 有趣,不是嗎? 這種模式也非常有用,并且經常會遇到 [**Java 面試問題**](//howtodoinjava.com/java/interviews-questions/core-java-interview-questions-series-part-1/ "Core java interview questions series : Part 1")關于[**設計模式**](//howtodoinjava.com/category/design-patterns/ "design patterns")的問題。 在這篇文章中,我們將討論以下幾點: * 設計參與者 * 問題陳述 * 使用裝飾器設計模式的建議解決方案 * 常見面試問題 * 一些實際用法 ## 設計參與者 裝飾器模式的典型示意圖如下所示。 ![decorator design pattern participants](https://img.kancloud.cn/0b/1a/0b1a0e928525204f82205f8b7d2cea1d_400x317.png) 裝飾設計模式參與者 以下是“裝飾器設計”模式的參與者: * **`Component`** – 這是包裝器,在運行時可以具有與其相關的其他職責。 * **`ConcreteComponent`** – 是在程序中添加了其他職責的原始對象。 * **`Decorator`** - 這是一個抽象類,其中包含對組件對象的引用,并且還實現了組件接口。 * **`ConcreteDecorator`** - 它們擴展了裝飾器,并在`Component`類的頂部構建了附加功能。 如果您仔細閱讀這兩行內容,那么您將了解它的工作方式如下: 您有一個實例,并將另一個實例放入其中。 它們都支持相同(或相似)的接口。 外面的一個是“裝飾器”。 您在外面用一個。 它可以掩蓋,更改或通過其內部實例的方法。 我總是喜歡以身作則。 因此,讓我們解決一個問題。 ## 問題陳述 讓我們有一個常見的用例,我們必須將所有用戶創建的報告顯示給管理員。 現在,這些報告可以屬于這些類別。 * 客戶報告 * 支持報告 這兩個報告**都必須具有第一列作為到原始報告的鏈接**,并且它們應具有**不同的顏色**。 可能應在**不同彈出窗口大小**中打開它們。 這些只是很少的事情,現實中可以實現很多。 一種**可能的方法是擴展`Report`對象**,然后具有兩個單獨的類`ClientReport`和`SupportReport`。 在這兩種方法中,定義私有方法,例如`makeAnchorLink()`,`designPopup()`,`applyColor()`等。 現在,在第一列數據單元格的某些獲取器方法中調用這些方法。 ![SubClassing](https://img.kancloud.cn/b8/3f/b83fc60d1621f53af2bb4781824b0b15_888x346.png "SubClassing") 如果您在此處停止并且不再修改系統,則它將起作用。 但是,假設幾天后,**您被告知為兩種報告應用不同的背景色**。 現在,您只有一種方法可以在兩個類中定義方法`colorBackground()`,并進行適當的調用。 將來系統中有更多報告時,問題將變得更加嚴重。 上面的解決方案明顯違反了 [**SMART 類別設計**](//howtodoinjava.com/best-practices/5-class-design-principles-solid-in-java/ "SMART principles for class design")中提到的**開閉原則**。 ## 使用裝飾器設計模式的建議解決方案 上面的問題是裝飾模式的理想選擇。 請記住,當我們有一個需要擴展但設計不當的對象時,請進行裝飾。 通過下面的類圖可以輕松解決以上問題。 在這里,我僅用于支持報告。 也可以為客戶報告構建類似的類層次結構。 ![Decorator Pattern Solution](https://img.kancloud.cn/20/c5/20c53baf07c0e78e5f5063b28cf7388c_960x550.png "Decorator Pattern Solution") 裝飾器模式解決方案 如果我們已經實現了這樣的解決方案,那么將來任何時候我們都可以添加其他修飾,而無需修改現有的類層次結構。 那是我們開始這篇文章的最終目標,對吧? ## 源代碼列表 讓我們看一看類的源代碼,以了解其實際外觀。 **`Report.java`** ```java public interface Report { public Object[][] getReportData(final String reportId); public String getFirstColumnData(); } ``` **`SupportReport.java`** ```java public class SupportReport implements Report { @Override public Object[][] getReportData(String reportId) { return null; } @Override public String getFirstColumnData() { return "Support data"; } } ``` **`ColumDecorator.java`** ```java public abstract class ColumDecorator implements Report { private Report decoratedReport; public ColumDecorator(Report report){ this.decoratedReport = report; } public String getFirstColumnData() { return decoratedReport.getFirstColumnData(); } @Override public Object[][] getReportData(String reportId) { return decoratedReport.getReportData(reportId); } } ``` **`SupportLinkDecorator.java`** ```java public class SupportLinkDecorator extends ColumDecorator{ public SupportLinkDecorator(Report report) { super(report); } public String getFirstColumnData() { return addMoreInfo (super.getFirstColumnData()) ; } private String addMoreInfo(String data){ return data + " - support link - "; } } ``` **`SupportPopupDecorator.java`** ```java public class SupportPopupDecorator extends ColumDecorator{ public SupportPopupDecorator(Report report) { super(report); } public String getFirstColumnData() { return addPopup (super.getFirstColumnData()) ; } private String addPopup(String data){ return data + " - support popup - "; } } ``` **`DecoratorPatternTest.java`** ```java public class DecoratorPatternTest { public static void main(String[] args) { //ClientPopupDecorator popupDecoratored = new ClientPopupDecorator(new ClientLinkDecorator(new ClientReport())); //System.out.println(popupDecoratored.getFirstColumnData()); SupportPopupDecorator supportPopupDecoratored = new SupportPopupDecorator(new SupportLinkDecorator(new SupportReport())); System.out.println(supportPopupDecoratored.getFirstColumnData()); } } Output: Support data - support link - - support popup - ``` 要下載完整的源代碼和 UML 圖,請遵循文章結尾處的下載鏈接。 ## 關于裝飾模式的面試問題 **A)如何確定何時使用裝飾器模式?** 如果我們深入了解該概念,則會發現裝飾器設計模式具有多個需求指標以表明這是潛在的解決方案,例如: * 我們有一個需要擴展的對象。 例如一個需要其他“可選”功能(例如滾動條,標題欄和狀態欄)的窗口控件。 * 幾個通過“裝飾”支持擴展的對象。 通常,這些對象共享一個公共接口,特征或超類,有時還具有其他中間超類。 * 裝飾的對象(類或原型實例化)和裝飾器對象具有一個或幾個共同的特征。 為了確保該功能,裝飾器&的裝飾器具有公共接口,特征或類繼承。 **B)裝飾器模式和適配器模式之間的區別** 不可以。適配器模式用于將對象的接口轉換為其他內容。 裝飾器模式用于擴展對象的功能,同時保持其接口。 由于它們都“包裹”了一個對象,因此兩者有時有時也被稱為“包裝模式”。 **C)裝飾器模式與子類別之間的差異** 裝飾器模式和子類之間的區別在于,在子類中,您可以“使用單個類”修飾實現接口的任何類。 假設我想給自己一個`java.util.Map`,每當我添加或刪除鍵時,它都會打印一條消息。 如果我只實際使用過`java.util.HashMap`,那么我可以創建`PrintingMap`嗎? 作為`HashMap`的子類并覆蓋&刪除。 但是,如果要創建`TreeMap`的打印版本,則可以創建`PrintingTreeMap`? (哪些代碼與`PrintingMap`具有幾乎相同的代碼? ## 裝飾器模式的常用用法: 1)Java IO 庫類,例如`BufferedInputStream bs = new BufferedInputStream(new FileInputStream(new File("File1.txt")))`; 2)在顯示標簽 jsp 庫中的裝飾器列中,例如: ```java <display:table name="reportsViewResultTable" class="demoClass" id="reportsQueryViewResultTable"> <display:column title="Report Id" sortable="true" property="reportDisplayId" decorator="com.comp.FirstColumnDataDecorator"></display:column> </display:table> ``` 3)在 **sitemesh** 中使用裝飾器,以提供一致的 UI 體驗。 [**源碼下載**](https://docs.google.com/file/d/0B7yo2HclmjI4RTREbG9ReDc5V2M/edit?usp=sharing) **祝您學習愉快!**
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看