为什么要用Adpater模式,什么时候用Adapter模式
我们之前在分析slf4j的时候,有说到slf4j的设计主要用到了Adapter模式和Facade模式。我们通过slf4j就可以很清楚的知道什么要用适配器模式。slf4j想提供给用户一种更加友好方便的接口(比如实现了{}通配符等)。而Log4j是已经存在的一个日志框架,该框架是没有slf4j对应接口的实现的,也就是说不兼容的,这个时候就需要用Adapter模式来把Log4j中的实现类转化为对用户可用的slf4j接口实现类。slf4j里面是使用了对象适配器模式,通过组合的方式实现。通常来说,适配器模式都不会用在软件一开始的设计中,往往都是一种软件后期优化过程中诞生的一种补偿模式,例如,Log4j的开发人员想提供给用户给好的体验,从而开发了slf4j日志接口框架,而Log4j是已经存在的框架了,为了不重新再写一套新的实现,就通过适配器模式,把Log4j实现类转化为实现slf4j接口的实现类。
总结:
- 为什么用适配器模式
为了协调不兼容的结构。
- 什么时候适配器模式
一般来说,是不会在设计初期使用,往往在后期优化中使用,是一种补偿机制。
Adapter模式的简单讲解
由上面的分析,我们知道,适配器的存在,就是为了将已存在的东西(接口)转换成适合我们的需要。
在适配器模式中引入了一个被称为适配器(Adapter)的包装类,而它所包装的对象称为适配者(Adaptee),即被适配的类。适配器的实现就是把客户类的请求转化为对适配者的相应接口的调用。也就是说:当客户类调用适配器的方法时,在适配器类的内部将调用适配者类的方法,而这个过程对客户类是透明的,客户类并不直接访问适配者类。因此,适配器让那些由于接口不兼容而不能交互的类可以一起工作。
在适配器模式中,我们通过增加一个新的适配器类来解决接口不兼容的问题,使得原本没有任何关系的类可以协同工作。根据适配器类与适配者类的关系不同,适配器模式可分为对象适配器和类适配器两种,在对象适配器模式中,适配器与适配者之间是关联关系;在类适配器模式中,适配器与适配者之间是继承(或实现)关系。
- 对象适配器模式
我们来看下使用的较多的对象适配器模式
适配者类
public class Adaptee {
public void specificRequest() {
System.out.println("被适配类具有 特殊功能...");
}
}
对外的接口(用户调用的接口)
public interface Target {
public void request();
}
适配器类,适配器类中有一个适配者类的属性,每次new一个适配器类的时候,都会将适配者实例注入适配器类,所以当调用适配器类的时候,实际执行的是适配者类中的方法。
public class Adapter implements Target {
private Adaptee adaptee;
public Adapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
public void request() {
// TODO Auto-generated method stub
adaptee.specificRequest();
}
}
public class AdapterTest {
@Test
public void test() {
// 使用普通功能类
Target concreteTarget = new ConcreteTarget();
concreteTarget.request();
// 使用特殊功能类,即适配类,
// 需要先创建一个被适配类的对象作为参数
Target adapter = new Adapter(new Adaptee());
adapter.request();
}
}
- 类适配器模式
类适配器,继承适配者类,通过继承关系,直接调用适配者类中的方法。
public class Adapter extends Adaptee implements Target {
public void request() {
// TODO Auto-generated method stub
super.specificRequest();
}
}