适配器模式主要解决当客户端需要使用一个已有的目标类时,该目标类的功能可以满足客户端的需要,但是该目标类所提供的接口无法让客户端直接使用,因此需要对目标类进行转换适配,使得无需改变其结构方法即可被客户端直接使用;如何实现不改变目标类的方法,而同时又能满足现有客户端的要求呢;解决办法就是引入一个适配器类,让适配器类提供客户端需要的接口,同时适配器内部依赖目标类,客户端只需要耦合适配器类,这样当客户端调用适配器方法时,实际上是去委托给目标类进行处理,而在此过程中,客户端与目标类没有发生耦合;适配器模式主要有依赖和继承两种方式,而又继承之间的需要强烈的”is a”的关系,因此实际使用中以依赖委托的方式居多;下面看一个案例:
系统中包含AdvancedUser和Admin两个不同权限的用户类,AdvancedUser具有一个login登录的方法, Admin具有一个更高优先级的删除用户deleteUser的方法:
1 | public class AdvancedUser { |
突然某一天我们要给AdvancedUser扩大权限,使其也具有删除用户的权限,因为当前已存在删除用户的功能在Admin用户中,因此我们提供接口适配器类IPremAdapter:
1 | public interface IPremAdapter { |
同时我们基于继承让AdvancedUser继承Admin实现适配器类IPremAdapter:
1 | public class AdvancedUser extends Admin implements IPremAdapter { |
对应的类图如下:
这样我们既没有没有修改目标类Admin,同时又把删除用户的功能适配给了AdvancedUser,通过继承把功能委托给父类去实现,这就是继承适配器模式;这种方式的的缺点就是继承带来的代码耦合,同时客户端类和目标类的关系也不一定是继承关系,设计不当会使将来系统的扩展性降低,因此实际通常使用依赖关系是客户端类委托给适配器类,而适配器类又把最终的功能委托给目标类来实现:
1 | public class PremAdapter { |
对应类图如下: