我正在设计一个我必须做的项目。为此,我曾想过使用装饰设计模式。但是,我必须将我的设计调整为项目的现有实施。然后,我无法完全保留装饰设计模式。
该项目有一个抽象基类(称为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()的每个调用创建一个不同的匿名类。
真的,我不知道是否可以这样做,还是有另一种更好的方式。
任何帮助将不胜感激!
答案 0 :(得分:2)
回答第一期:
将接口I放在A上,以便装饰者/代表可以实现相同的接口,或者
创建一个接口I(相当于A的api)和一个包装类AW,它包装A并通过将所有调用直接传递给它来实现我。
将您的客户端代码转换为使用I而不是A,然后您可以愉快地使用在AW中“包裹”旧crunk的新界面来构建装饰器/代理。
出现的一个值得注意的问题是,使用A(IdentityHashMaps,持久性)的某些代码样式可能需要引用“底层”A.如果出现这种情况,您可以在接口{{1}中放置一个方法}。尽量避免使用太多,因为它显然绕过了所有的装饰。
第二个问题:装饰子类型。
这里的问题是子类型是否需要作为不同的装饰器类型公开 - 或者是否可以暴露一个统一的装饰器,(可能,如果需要)在内部意识到A子类型的类型系统可以包装。
如果这些亚型是众所周知的&amp;稳定,你可以在界面中实现“句柄样式”api。例如,对于文件系统实体,您将呈现单一类型的句柄,但提供getUnderlyingA()
,isFile()
,isDirectory()
,isDevice()
,isDrive()
等询问类型的方法。可以使用isRaw()
方法使用目录子类型。
我的问题是为什么你需要外部访问(从装饰器)到受保护的方法?如果你这样做,那些方法应该是公开的,并且原始设计被破坏/不够可扩展。
也许你可以在同一个包中创建一个静态帮助器类(如果没有改变A类本身),这将使你能够从装饰器中正确访问这个遗留的crunk。
这里有一点,正确地完成工作有时会涉及到&amp;可能升级遗留代码。如果没有效率的&amp;可维护的设计替代方案,这不应该是一个完全的问题。加倍类型系统(创建两个平行的heirarchies)绝对不是你应该做的。
如果没有好的方法可以做到这一点,你应该处理其他事情(不同的功能/要求),而不是让代码库更糟糕。