【设计模式】适配器模式、装饰模式、代理模式的异同

这三种设计模式同属于结构型模式,初学者乍一看可能难以分辨三者的区别。这里对三者之间的异同详细地探讨一下。web

适配器模式VS装饰模式

首先来比较一下适配器模式和装饰模式。二者都被称为包装模式,在功能上是较为接近的。设计模式

适配器模式分为类适配器和对象适配器。类适配器比较直接,继承待适配类,实现目标接口,使得待适配类知足目标接口的特定功能。可是这种直接继承的方法太简单粗暴了,咱们知道要尽可能多聚合少继承,因此更提倡使用下面的对象适配器。安全

对象适配器是此次对比的主角,适配器持有一个待适配的对象而且实现了目标接口。经过使用适配器模式,能够大大提高程序的灵活性以及代码的可重复性。svg

与之相对,装饰者实现待装饰接口或继承待装饰类的同时持有一个待装饰的实例,以此来为待装饰类提供加强的功能。相较于继承来讲,装饰模式更为灵活,但使用装饰模式会产生比使用继承关系更多的对象。更多的对象会使得查错变得困难,特别是这些对象看上去都很相像。函数

结构上的不一样在于从类图中能够看出,装饰模式持有和继承的通常是同一个类或接口,而适配器持有的是待适配的对象,实现的是目标接口。设计

功能上的不一样在于装饰模式中装饰过的类力求与原来对外接口一致。这使得在调用方看来,装饰事后的类与以前没有什么区别,只是某一方面功能加强了。可是适配器模式中适配器则扩展了待适配类新的功能。简单来讲,**装饰模式加强了原有功能,适配器模式拓展了新的功能。**咱们也能够看出,装饰模式与适配器模式是不冲突的,能够既加强原有功能,又添加全新的功能。代理

装饰模式VS代理模式

从类图中能够看代理模式和装饰模式是一致的。这里我要先说明一下,有不少人执着于代理模式的被代理对象是在代理对象的构造函数中new出来的,而不是传进去的参数,而且以此来区分装饰模式和代理模式。我我的认为这是有些偏颇的。好比对于动态代理来讲,被代理方确定要做为参数传入代理方中。xml

在我看来二者的区别在于:代理模式中,代理方对被代理方有控制权,对于调用方来讲二者是分工十分清楚的两个类,调用者很清楚它调用的是代理方。代理方的构造函数能够有多个参数,这使得它能够根据外界环境决定被代理方的运行与否。装饰模式中,装饰者这是加强了被装饰者的某种功能,对于调用方来讲二者几乎没有区别。对象

总结

代理持有一个对象,根据外界环境决定代理的行为,出于某种缘由(远程,安全)不直接去调用对象。继承

适配器是相对固定的转换成某种指定的功能,因为接口不兼容。

装饰模式主要用于添加新的功能,缺点是类的结构变复杂且不易区分。