有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java中的装饰器设计模式

我正在设计一个我必须做的项目。为此,我考虑使用decorator设计模式。然而,我必须调整我的设计以适应项目的现有实施。那么,我不能完全保留装饰设计模式

该项目有一个抽象基类(称为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具有只能从自己的类或子类访问的受保护方法。因为我需要访问这些方法,所以我不能使用decorator设计模式

第二种选择

我可以用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)

我在哪儿。get是一种静态方法

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

我的问题是,是否有可能实现一个继承A1,A2。。。 每次打电话给BMaker。get()应该创建一个不同的匿名类,如果BMaker的第一个参数为depending。get()是A1、A2、A3

真的,我不知道是否有可能做到这一点,或者是否有其他更好的方法

任何帮助都将不胜感激


共 (1) 个答案

  1. # 1 楼答案

    对第一个问题的答复:

    1. 或者将接口I放在一个面板上,以便您的装饰者/代理可以实现相同的接口,或者

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

    将您的客户机代码转换为使用I而不是A,然后您就可以愉快地继续使用新接口构建decorators/或委托,并将旧的crunk“包装”到AW中

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


    第二个问题:装饰子类型

    这里的问题是子类型是否需要作为不同的装饰器类型公开,或者是否可以公开一个统一的装饰器,这(可能,若必要的话)在内部知道它可以包装的子类型的类型系统

    如果子类型是众所周知的&;稳定,您可以在接口中实现“句柄样式”api。例如,对于文件系统实体,您可以提供一个单一类型的句柄,但可以提供isFile()isDirectory()isDevice()isDrive()isRaw()等方法来查询类型。可以使用listFiles()方法使用目录子类型

    我的问题是,为什么需要外部访问(从装饰程序)受保护的方法?如果您这样做,这些方法应该是公共的,并且原始设计被破坏/扩展不足

    也许您可以在同一个包中创建一个静态帮助器类(如果不更改a类本身的话),这样您就可以从装饰器中正确地访问这个遗留的crunk


    这里有一个特定的点,正确地完成你的工作有时确实需要与&;可能升级遗留代码。如果没有一个高效的&;可维护的设计方案,这不应该是一个总的症结所在。将类型系统加倍(创建两个平行的继承人)绝对不是您应该做的事情

    如果没有一个好的方法可以做到这一点,那么您应该做一些其他的事情(不同的特性/需求),而不是让代码库变得更糟