作者:工匠若水
问:代理模式和装饰者模式有什么区别?
答:这是一道非常经典的设计模式相关问题,在回答具体问题前咱们先来看看这两种设计模式的 UML 类图,他们分别描述了装饰器模式和代理模式的基本实现。
可以看见,这两个图会使我们产生困惑,因为他们看起来很像。对装饰器模式来说,装饰者(decorator)和被装饰者(decoratee)都实现同一个接口。对代理模式来说,代理类(proxy class)和真实处理的类(real class)都实现同一个接口。此外,不论我们使用哪一个模式,都可以很容易地在真实对象的方法前面或者后面加上自定义的方法。
而实际上,在装饰器模式和代理模式之间还是有很多差别的。装饰器模式关注于在一个对象上动态的添加方法,而代理模式关注于控制对对象的访问。换句话说,用代理模式,代理类(proxy class)可以对它的客户隐藏一个对象的具体信息,因此,当使用代理模式的时候,我们常常在一个代理类中创建一个对象的实例。而当我们使用装饰器模式的时候,我们通常的做法是将原始对象作为一个参数传给装饰者的构造器。
上面就是其区别,如果非要总结成简单明了的区别,那么我们可以得到如下结论:
装饰模式:
- 在不改变接口的前提下,动态扩展对象的访问。
- 动态继承,让类具有在运行期改变行为的能力(来自多态特性)。
- 装饰模式,突出的是运行期增加行为,这和继承是不同的,继承是在编译期增加行为。
- 强调:增强。
代理模式:
- 在不改变接口的前提下,控制对象的访问。
- 从封装的角度讲,是为了解决类与类之间相互调用而由此导致的耦合关系,可以说是接口的另外一个层引用。比如:在a类->b代理->c类这个关系中,c类的一切行为都隐藏在b中。即调用者不知道要访问的内容与代理了什么对象。
- 从复用的角度讲,可以解决不同类调用一个复杂类时,仅仅因较小的改变而导致整个复杂类新建一个类。比如:a类->c类1;b类->c类2,可以变为a类->ca代理类->c类;b类->cb代理类-c类。
- 代理模式,是类之间的封装和(某方面的)复用。
- 强调:限制。