简述
运行时,为原对象拓展新的行为。
相较于传统的继承来拓展新的行为,装饰器模式更为的灵活多变,当然实现起来也更为复杂。
话不多说,看个优化案例吧。
优化案例
最初版v0
现有系统中有设定窗口Style的模块,现在想增加一个圆角的样式。以下是现有模块的代码。
1 2 3 4 5
| class Style { public void style() { System.out.println("设置Order"); } }
|
第一种传统的修改方式。
1 2 3 4 5 6
| class Style { public void style() { System.out.println("设置Order"); System.out.println("设置Radius"); } }
|
虽然代码简单,但细想一下,如果我们日后仍然需要单独设置Order的样式怎么办。现在的代码实现已经无法满足了不是?
为此,我们可能会想到另一种方案。使用继承。
1 2 3 4 5 6 7 8 9 10 11
| class BaseStyle { public void style() { System.out.println("设置Order"); } } class Radius extends BaseStyle { public void style() { super.style(); System.out.println("设置Radius"); } }
|
确实,如果不在意类的命名的话,目前来看这确实是个好的选择。请注意,只是目前来看。设计不只着眼与当前,而是需要放眼未来。什么意思呢?比如,当未来需要添加一个Color样式的时候怎么办,有人可能认为添加再添加一个BassStyle类的子类Color就好了;如果客户就只要一个单独的Color样式呢,或者说需要一个可以设置Radius和Color的样式。再超前一些,客户如果想要的是增加一个样式,且可以与现有的任何一种或多种样式随意组合呢?又该怎么办?传统的继承已经搞不了了呀。
别慌,最后这一种需求正好就是使用装饰器模式的目的。我们来看看改进后的案例吧。
修改版v1
使用装饰器模式优化上述需求,使得任意样式间可以任意组合,这种任意组合包括任意种类和数量。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| public interface Style { void style(); } public class Order implements Style { @Override public void style() { System.out.println("设置Order"); } } public class Radius implements Style { @Override public void style() { System.out.println("设置Radius"); } }
public class Color implements Style { @Override public void style() { System.out.println("设置Color"); } } public class OrderDecorator implements Style { private Style style; public OrderDecorator(Style target) { this.style = target; } @Override public void style() { style.style(); decorator(); } private void decorator() { System.out.println("设置Order"); } } public class RadiusDecorator implements Style { private Style style; public RadiusDecorator(Style target) { this.style = target; } @Override public void style() { style.style(); decorator(); } private void decorator() { System.out.println("设置Radius"); } } public class ColorDecorator implements Style { private Style style; public ColorDecorator(Style target) { this.style = target; } @Override public void style() { style.style(); decorator(); } private void decorator() { System.out.println("设置Color"); } }
|
定义三个装饰器类:OrderDecorator
, RadiusDecorator
, ColorDecorator
分别实现Style
接口,定义decorator
方法用(动态拓展的核心方法之一)。调用完`target
的style
方法后调用decorator
方法实现功能的动态拓展。接着,看看客户端如何使用。
1 2 3 4 5 6 7 8
| public class Client { public static void main(String[] args) { Style style = new Order(); Style style1 = new ColorDecorator(style); Style style2 = new RadiusDecorator(style1); style2.style(); } }
|
输出结果:
1 2 3
| 设置Order 设置Color 设置Radius
|
修改版v2
上述优化可以看到一些重复冗余的代码,还有再次优化的空间。以下是实现样例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| public interface Style { void style(); } public class Order implements Style { @Override public void style() { System.out.println("设置Order"); } } public class Radius implements Style { @Override public void style() { System.out.println("设置Radius"); } } public class Color implements Style { @Override public void style() { System.out.println("设置Color"); } } public abstract class StyleDecorator implements Style { protected Style style; public StyleDecorator(Style target) { this.style = target; } @Override public void style() { style.style(); decorator(); } protected abstract void decorator(); } public class OrderDecorator extends StyleDecorator { public OrderDecorator(Style target) { super(target); } @Override protected void decorator() { System.out.println("设置Order"); } } public class RadiusDecorator extends StyleDecorator { public RadiusDecorator(Style target) { super(target); } @Override protected void decorator() { System.out.println("设置Radius"); } } public class ColorDecorator extends StyleDecorator { public ColorDecorator(Style target) { super(target); } @Override protected void decorator() { System.out.println("设置Color"); } }
|
客户端的使用和输出结果还是和v1一样。
1 2 3 4 5 6 7 8
| public class Client { public static void main(String[] args) { Style style = new Order(); Style style1 = new ColorDecorator(style); Style style2 = new RadiusDecorator(style1); style2.style(); } }
|
输出结果:
1 2 3
| 设置Order 设置Color 设置Radius
|
新建高层抽象类,讲冗余的方法属性都打包到抽象类中,减少重复的代码。
这个应该属于题外话了,可以见得设计模式的实现方式是多种多样的。不要过度拘泥于模板。只要能达成目的,想怎么设计就可以怎么设计。
修改版v1和v2都是装饰器模式,实际开发根据需求斟酌即可。
总结
优点
- 开发时可以自由组合各种各样的功能。
- 新增的功能对于现有功能没有任何的影响。
缺点
- 增加系统的复杂度。
- 对于开发人员的技术要求提高。
应用场景
- 需要灵活组合功能的场合。
- 限制继承,但又想拓展类的功能的场合。