在java中的装饰设计模式

时间:2013-11-02 23:31:29

标签: java design-patterns inheritance anonymous-class

我正在设计一个我必须做的项目。为此,我曾想过使用装饰设计模式。但是,我必须将我的设计调整为项目的现有实施。然后,我无法完全保留装饰设计模式。

该项目有一个抽象基类(称为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,A2,A3,......,则应该对BMaker.get()的每个调用创建一个不同的匿名类。

真的,我不知道是否可以这样做,还是有另一种更好的方式。

任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:2)

回答第一期:

  1. 将接口I放在A上,以便装饰者/代表可以实现相同的接口,或者

  2. 创建一个接口I(相当于A的api)和一个包装类AW,它包装A并通过将所有调用直接传递给它来实现我。

  3. 将您的客户端代码转换为使用I而不是A,然后您可以愉快地使用在AW中“包裹”旧crunk的新界面来构建装饰器/代理。

    出现的一个值得注意的问题是,使用A(IdentityHashMaps,持久性)的某些代码样式可能需要引用“底层”A.如果出现这种情况,您可以在接口{{1}中放置一个方法}。尽量避免使用太多,因为它显然绕过了所有的装饰。


    第二个问题:装饰子类型。

    这里的问题是子类型是否需要作为不同的装饰器类型公开 - 或者是否可以暴露一个统一的装饰器,(可能,如果需要)在内部意识到A子类型的类型系统可以包装。

    如果这些亚型是众所周知的&amp;稳定,你可以在界面中实现“句柄样式”api。例如,对于文件系统实体,您将呈现单一类型的句柄,但提供getUnderlyingA()isFile()isDirectory()isDevice()isDrive()询问类型的方法。可以使用isRaw()方法使用目录子类型。

    我的问题是为什么你需要外部访问(从装饰器)到受保护的方法?如果你这样做,那些方法应该是公开的,并且原始设计被破坏/不够可扩展。

    也许你可以在同一个包中创建一个静态帮助器类(如果没有改变A类本身),这将使你能够从装饰器中正确访问这个遗留的crunk。


    这里有一点,正确地完成工作有时会涉及到&amp;可能升级遗留代码。如果没有效率的&amp;可维护的设计替代方案,这不应该是一个完全的问题。加倍类型系统(创建两个平行的heirarchies)绝对不是你应该做的。

    如果没有好的方法可以做到这一点,你应该处理其他事情(不同的功能/要求),而不是让代码库更糟糕。