一、代理模式和装饰者模式
还记得装饰者模式那个开咖啡店的例子吗?
装饰者类图:
同样开咖啡店,使用代理模式,那么类图是这样的
看起来是不是特别像?
对装饰者模式来说,装饰者(各种调料)和被装饰者(各种咖啡)都实现同一个接口(饮料)。对代理模式来说,代理类(各种咖啡的代理)和真实处理的类(各种咖啡)也都实现同一个接口(饮料)。此外,不论我们使用哪一个模式,都可以很容易地在真实对象的方法前面或者后面加上自定义的方法。
但是装饰者模式可以让使用者直观的看到增强了哪些功能(可以知道加了牛奶,奶泡等),而代理模式完全限制了使用者,只去调用代理,至于代理里面增加了什么功能,使用者是不知道,隐藏了一个对象的具体信息。因此,当我们使用装饰器模式的时候,通常将原始对象作为一个参数传给装饰者的构造器,而使用代理模式的时候,是在一个代理类中创建一个对象的实例。代理和真实对象之间的的关系通常在编译时就已经确定了,而装饰者能够在运行时递归地被构造。
看看代码:
代理模式:
public class Proxy implements Subject{
private Subject subject;
public Proxy(){
//关系在编译时确定
subject = new RealSubject();
...//其他操作
}
}
//代理的客户
public class Client{
public static void main(String[] args){
//客户不知道代理委托了另一个对象
Subject subject = new Proxy();
…
}
}
装饰者模式:
public class Decorator implements Component{
private Component component;
public Decorator(Component component){
//由外部传入,在运行时构造
this.component = component
...//其他操作
}
}
//装饰器的客户
public class Client{
public static void main(String[] args){
//客户指定了装饰者需要装饰的是哪一个类
Component component = new Decorator(new ConcreteComponent());
…
}
}
总结:
装饰者模式:在不改变接口的前提下,动态扩展对象的功能
代理模式:在不改变接口的前提下,控制对象的访问
装饰者模式强调功能扩展,比如A对象的B方法,运用装饰模式后,在调用B方法前后增加了新的功能,此时B方法效果与原来不同(咖啡店的例子,用户知道得到的是加了牛奶和奶泡的深焙咖啡,这杯深焙咖啡与原有的深焙咖啡不同)
代理模式强调控制访问,在调用B方法前后加入的方法是用来控制怎么访问B方法的原始数据,而对于B实现的功能效果不做修改(咖啡店的例子,用户只知道得到的是一杯深焙咖啡,里面有没有牛奶等调料是不知道的,功能也是卖给用户一杯咖啡,这个功能是没有变化的)
二、装饰者模式和继承
如果要加强一个类或对象的功能,可以通过继承然后重写父类方法来加强父类的一些功能,也可以重新定义某些属性,即覆盖父类的原有属性和方法,使其获得与父类不同的功能。而装饰者模式的最基本的功能就是对传入的一个对象进行功能的加强与优化。那么他们之间又有什么区别呢?
还是以咖啡店为例,如果用继承的方法,类图是这样的:
简直就是类的大爆炸,所以用装饰者模式就可以很好的解决这个问题了。