设计模式--适配器模式
简介
适配器模式(Adapter Pattern)又叫做变压器模式,它的功能是将一个类的接口变成客户端所期望的另一种接口,从而使原本因接口不匹配导致无法在一起工作的两个类能够一起工作,属于结构设计模式。
也就是说,当前系统存在两种接口A和B,客户只支持访问A接口,但是当前系统没有A接口对象,但是有B接口对象,但客户无法识别B接口,因此需要通过一个适配器C,将B接口转化成A接口,从而使得客户能够从A接口获取得到B接口的内容。
在软件开发中,基本上任何问题都可以通过增加一个中间层进行解决。适配器模式其实就是中间层。综上。适配器模式其实起到了转化/委托的作用,将一种接口转化为另一种符合需求的接口。
适配器的使用场景
提供一个转化器(适配器),将当前系统存在的一个对象转化为客户端能够访问的接口对象。适配器适用于以下几种业务场景:
1、已经存在的类,它的方法和需求不匹配(方法结果相同或相似)的情况。
2、适配器模式不是软件设计阶段考虑的设计模式,是随着软件维护,由不同产品、不同厂家造成功能类似而接口不相同情况下的解决方案。
适配器UML图:
适配器模式一般包含三种角色:
目标角色(Target):也就是我们期望的接口;
原角色(Adaptee):存在于系统中,内容满足客户需求(需转换),但接口不匹配的接口实例;
适配器(Adapter):将源角色(Adapter)转化为目标角色(Target)的类实例;
适配器模式各角色之间的关系:
假设当前系统中,客户端需要访问的是Target接口,但是Target接口没有一个符合需求,而Adaptee实例符合需求;但是客户端无法直接使用Adaptee(接口不兼容);因此,我们需要一个适配器(Adapter)来进行中转,让Adaptee转化为Target接口形式;
适配器模式有3中形式:类适配器、对象适配器、接口适配器。
类适配器:让Adapter实现Target接口,并且继承Adaptee,这样Adapter就具备Target和Adaptee的特性,就可以将两者进行转化。
public class Adapter extends Adaptee implements Target{
...
}
对象适配器:对象适配器的原理就是通过组合来实现适配器功能。具体做法:让Adapter实现Target接口,然后内部持有Adaptee实例,然后再Target接口规定的方法内转换Adaptee。
public class Adapter implements Target{
private Adaptee adaptee;
public Adapter(Adaptee adaptee;){
this.adaptee = adaptee;
}
...
}
接口适配器:类适配器和对象适配器着重于将系统存在的一个角色(Adaptee)转化为目标(Target)所需内容,而接口适配器的使用场景是解决接口方法过多,如果直接实现接口,那么类会多出许多空实现的方法,类显得很臃肿。此时,使用接口适配器就能让我们只实现我们需要的接口方法,目标更清晰。
public abstract class DefaultAdapter implements Target{
@Override
public void sourceToTarget(){
}
...
}
public class SourceAdapter extends DefaultAdapter{
private Adaptee adaptee;
public Adapter(Adaptee adaptee;){
this.adaptee = adaptee;
}
@Override
public void sourceToTarget(){
}
...
}
至于为什么中间类使用抽象类,相信你看过我介绍的软件六大设计原则,就明白了。它需要符合里氏替换原则(尽量基于抽象类和接口的继承)。
适配器模式和策略模式区别
适配器模式主要是解决功能兼容问题,单个场景容易区分。适配器的实现逻辑并不依赖于接口。
源码中的使用
Spring中的AdvisorAdapter类
SpringMVC中的HandlerAdapter类
适配器模式和装饰器模式对比
装饰器和适配器模式都是包装模式(Wrapper Pattern),装饰器也是一种特殊的代理模式。
装饰器模式 | 适配器模式 | |
---|---|---|
形式 | 是一种非常特别的适配器模式 | 没有层级关系,装饰器有层级关系 |
定义 | 装饰器和被装饰器都可以实现同一个接口,主要目的是为了扩展之后依旧保留OOP关系 | 适配器和被适配器没有必然的联系,通常是采用继承或代理的形式进行包装 |
关系 | 满足is-a的关系 | 满足has-a的关系 |
功能 | 注重覆盖、扩展 | 注重兼容、转换 |
设计 | 前置考虑 | 后置考虑 |
适配器模式的优缺点
优点:
1、能提高类的透明性和复用,现有的类复用不需要改变。
2、目标类和适配器类解耦,提高程序的扩展性。
3、在很多业务场景中符合开闭原则。
缺点:
1、适配器编写过程需要全面考虑。可能会增加系统的复杂性。
2、增加代码阅读难度,降低代码可读性,过多使用适配器会使系统代码变得凌乱。