在讲适配器模式之前先介绍一下结构型模式,有助于理解适配器原则。
结构型模式
结构型模式,英文为Structure Pattern。结构型模式是描述如何将类或对象结合在一起,形成一个更大的结构,结构模式描述两种不同的东西:类与类的实例,可以分为类结构模式和对象结构模式1。
- 类结构模式使用继承来把类,接口等组合在一起,形成更大的结构。 当一个类从父类继承,并实现某接口时,这个新的类就把父类的结构和接口的结构结合起来。 类结构模式是静态的。一个类结构模式的典型的例子,就是类形式的适配器模式。
- 实例结构模式描述各种不同类型的把对象组合在一起,实现新的功能的方法。实例结构模式是动态的。
适配器模式
适配器模式概念
将一个类的接口转换成客户期望的另一个接口,从而使原本因接口不兼容而无法在一起工作的那些类能够在一起工作。适配器模式是结构型模式,结构型模式作用是从程序的结构上实现松耦合,从而可以扩大整体的类结构,用来解决更大的问题。
角色介绍
- 目标接口Target:客户所期待的接口,可以是具体类或抽象类,也可以是接口。
- 适配者类Adaptee:需要适配的类。
- 适配器Adapter:具体类,将Adaptee转换成Target。
有两种方式实现:
- 类适配器方式
继承适配者类Adaptee,实现将Adaptee转换成Target。 - 对象适配器方式
该方法通过在内部维护一个Adaptee对象引用,将Adaptee转换成Target。
- 类适配器方式
示例如下:
/**
* 实现适配器模式
* @author sywyg
* @since 2015/4/8
*/
public class Client{
public static void main(String[] args){
Adaptee adaptee = new Adaptee();
Target target = new Adapter(adaptee);
// 客户端实际需要的是Target接口
start(target);
}
public static void start(Target target){
//........
target.insert();
//........
}
}
/**
*适配器类
*目的是希望Adaptee接口适配Target接口
*/
class Adapter implements Target{
private Adaptee adaptee;//需要适配的接口
public Adapter(Adaptee adaptee){
this.adaptee = adaptee;
}
public void insert(){
adaptee.connect();
}
}
/**
*目标接口
*/
interface Target{
public void insert();
}
/**
*适配者类
*/
interface Adaptee{
public void connect(){
System.out.println("开始工作");
}
}
以上是对象适配器模式,即在适配器Adapter中维持一个适配者类Adaptee的引用。而对于类适配器模式,则是需要适配器Adapter继承适配者类Adaptee,不再给出示例。
两种适配器区别
- 类适配器使用继承的方式,属于静态定义方式;而对象适配器使用组合的方式,属于动态组合方式。
- 对于类适配器,可以通过覆盖适配者类的方法,增加适配器的灵活性。但是对于java单继承而言,无法再继承其它类。
- 对于对象适配器,适配器可以适配适配者类及其子类。但是如果我们需要覆盖适配者类的方法时,这种方式比较困难,需要定义适配者类的子类,然后让适配器组合该子类。
建议使用对象适配器方式,多用组合少用继承,但是也要具体问题具体分析。
使用场景
- 客户端需要使用现有的类,但是该类的接口并不符合客户端的接口,此时可以使用适配器模式。
- 旧系统的改造和升级
优缺点
优点
- 提高适配者的复用性。
- 容易扩展适配器。
缺点
过多的使用适配器模式,会让系统变得非常复杂。
- 阎宏的java与模式 ↩