簡體   English   中英

在java中的裝飾設計模式

[英]Decorator Design Pattern in java

我正在設計一個我必須做的項目。 為此,我曾想過使用裝飾設計模式。 但是,我必須將我的設計調整為項目的現有實施。 然后,我無法完全保留裝飾設計模式。

該項目有一個抽象基類(稱為A)和一組子類(稱為A1,A2,A3,A4等)。 我無法修改這些類的代碼。

然后,我必須為這些類添加額外的功能。 為此,我創建了一個用於類A(裝飾器)的抽象類(稱為B)。 我還創建了用於A1,A2,A3,A4類......的混凝土裝飾器。

注意:如您所見,我不使用任何接口,因為A類不使用任何接口,我無法修改此代碼。

但我在這個設計中看到了一些問題:

1)類B1,B2,B3,B4,...必須添加類A1,A2,A3,A4,......的所有方法,用於調用類A1,A2,A3,A4的方法...例如,在B1級:

    class B1 {
      public A1 objectA1;

      B1() {
          objectA1 = new A1();
      }

      public void add(int value) {
          objectA1.add(value);
          // extra funcionality
      } 
    }    

這可能是一個問題,因為如果其他開發人員修改類A,A1,A2,A3,A4,...的代碼,他們還需要修改B,B1,B2,B3,B4的代碼......我想要為了防止這種情況。

2)此外,類A,A1,A2,A3,A4具有只能從自己的類或子類訪問的受保護方法。 由於我需要訪問這些方法,我不能使用裝飾器設計模式。

第二替代方案

我可以用B1,B2,B3,B4擴展A1,A2,A3,A4類。 例如:

    class B1 extends A1 {

      B1() {
          objectA1 = new A1();
      }

      public void add(int value) {
          super.add(value);
          // extra funcionality
      } 
    }    

通過這種方式,我解決了第二個問題並避免覆蓋A1的所有方法,只覆蓋必要的方法。 即便如此,每次創建A的子類時,都需要創建相應的類B.我想要防止它因為B類(B1,B2,...)只需要重寫類的方法A(A1,A2,......)。

第三替代方案

然后,我認為我可以考慮將B類(B1,B2,...)作為A類(A1,A2,......)的包裝。 通過這種方式,將創建B的實例作為下一個:

    new BMaker.get(A1, params_of_constructor_A1)
    new BMaker.get(A2, params_of_constructor_A2)
    new BMaker.get(A3, params_of_constructor_A3)
    new BMaker.get(A4, params_of_constructor_A4) or 
    ...
    new BMaker.get(AN, params_of_constructor_AN)

其中BMaker.get是一個靜態方法。

    public static <T extends A> A get (T objectA, params ) {
        // return anonymous class (*1)
    }

我的問題是,是否可以實現一個繼承A1,A2,...的匿名類,如果BMaker.get()的第一個參數是A1,則應該對BMaker.get()的每個調用創建一個不同的匿名類。 ,A2,A3,...

真的,我不知道是否有可能做到這一點,還是有另一種更好的方法。

任何幫助,將不勝感激!

回答第一期:

  1. 要么將接口I放在A上,那么裝飾器/委托可以實現相同的接口,或者

  2. 創建一個接口I(相當於A的api)和一個包裝類AW,它包裝A並通過將所有調用直接傳遞給它來實現我。

將您的客戶端代碼轉換為使用I而不是A,然后您可以愉快地使用在AW中“包裹”舊crunk的新界面來構建裝飾器/代理。

出現的一個值得注意的問題是使用A(IdentityHashMaps,持久性)的某些樣式代碼可能需要引用“底層”A.如果出現這種情況,您可以在接口getUnderlyingA()放置一個方法。 盡量避免使用太多,因為它顯然繞過了所有的裝飾。


第二個問題:裝飾亞型。

這里的問題是子類型是否需要作為不同的裝飾器類型公開 - 或者是否可以暴露一個統一的裝飾器,(可能,如果需要)在內部知道它可以包裝的A子類型的類型系統。

如果子類型是眾所周知且穩定的,則可以在界面中實現“句柄樣式”api。 例如,對於文件系統實體,您將呈現單個類型的句柄,但提供isFile()isDirectory()isDevice()isDrive()isRaw()等用於查詢類型的方法。 可以使用listFiles()方法來使用目錄子類型。

我的問題是為什么你需要外部訪問(從裝飾器)到受保護的方法? 如果這樣做, 那些方法應該是公開的 ,並且原始設計被破壞/不夠可擴展。

也許你可以在同一個包中創建一個靜態幫助器類(如果沒有改變A類本身),這將使你能夠從裝飾器中正確訪問這個遺留的crunk。


這里有一點,正確地完成工作有時會涉及到並可能升級遺留代碼。 如果沒有一種有效且可維護的設計替代方案,那么這不應該是一個完全的問題。 加倍類型系統(創建兩個平行的heirarchies)絕對不是你應該做的。

如果沒有一個好方法可以做到這一點,你應該處理其他事情(一個不同的功能/要求),而不是使代碼庫更糟糕。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM