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 楼答案
对第一个问题的答复:
或者将接口I放在一个面板上,以便您的装饰者/代理可以实现相同的接口,或者
创建一个接口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
这里有一个特定的点,正确地完成你的工作有时确实需要与&;可能升级遗留代码。如果没有一个高效的&;可维护的设计方案,这不应该是一个总的症结所在。将类型系统加倍(创建两个平行的继承人)绝对不是您应该做的事情
如果没有一个好的方法可以做到这一点,那么您应该做一些其他的事情(不同的特性/需求),而不是让代码库变得更糟