文章目录
  1. 1. 模式定义
  2. 2. 模式结构
  3. 3. UML图
    1. 3.1. 类适配器UML图
    2. 3.2. 对象适配器UML图
  4. 4. 类适配器模式代码实现
    1. 4.1. Target.java
    2. 4.2. Adaptee.java
    3. 4.3. Adapter.java
    4. 4.4. 测试类
    5. 4.5. 运行结果
  5. 5. 对象适配器代码实现
    1. 5.1. Target.java
    2. 5.2. Adaptee.java
    3. 5.3. Adapter.java
    4. 5.4. 测试类
    5. 5.5. 运行结果
  6. 6. 模式分析
  7. 7. 适配器模式的优点
  8. 8. 适配器模式的缺点

今天我们来学习一种结构型模式,适配器模式(Adapter Pattern)。

模式定义

将一个接口转换成客户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。适配器模式有两种,一种是对象适配器,一种是类适配器。

模式结构

适配器模式包含如下角色:

Target: 目标抽象类
Adapter: 适配器类
Adaptee: 适配者类
Client: 客户类

UML图

类适配器UML图

对象适配器UML图

类适配器模式代码实现

Target.java

1
2
3
4
5
6
public interface Target {

void sampleOperation1();

void sampleOperation2();
}

Adaptee.java

1
2
3
4
5
6
public class Adaptee {

public void sampleOperation1() {
System.out.println("sampleOperation1");
}
}

Adapter.java

1
2
3
4
5
6
7
8
9

public class Adapter extends Adaptee implements Target {

@Override
public void sampleOperation2() {
System.out.println("sampleOperation2");
}

}

测试类

1
2
3
4
5
6
7
8
9

public class MyClass {

public static void main(String[] args) {
Adapter adapter = new Adapter();
adapter.sampleOperation1();
adapter.sampleOperation2();
}
}

运行结果

对象适配器代码实现

Target.java

1
2
3
4
5
6
7

public interface Target {

void sampleOperation1();

void sampleOperation2();
}

Adaptee.java

1
2
3
4
5
6
public class Adaptee {

public void sampleOperation1() {
System.out.println("sampleOperation1");
}
}

Adapter.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

public class Adapter implements Target {

private Adaptee mAdaptee;

public Adapter(Adaptee adaptee) {
mAdaptee = adaptee;
}

@Override
public void sampleOperation1() {
mAdaptee.sampleOperation1();
}

@Override
public void sampleOperation2() {
System.out.println("sampleOperation2");
}

}

测试类

1
2
3
4
5
6
7
8
9

public class MyClass {

public static void main(String[] args) {
Adapter adapter =new Adapter(new Adaptee());
adapter.sampleOperation1();
adapter.sampleOperation2();
}
}

运行结果

模式分析

  • 类适配器使用对象继承的方式,是静态的定义方式;而对象适配器使用对象组合的方式,是动态组合的方式。

  • 对于类适配器,由于适配器直接继承了Adaptee,使得适配器不能和Adaptee的子类一起工作,因为继承是静态的关系,当适配器继承了Adaptee后,就不可能再去处理 Adaptee的子类了。

  • 对于对象适配器,一个适配器可以把多种不同的源适配到同一个目标。换言之,同一个适配器可以把源类和它的子类都适配到目标接口。因为对象适配器采用的是对象组合的关系,只要对象类型正确,是不是子类都无所谓。

  • 对于类适配器,适配器可以重定义Adaptee的部分行为,相当于子类覆盖父类的部分实现方法。

  • 对于对象适配器,要重定义Adaptee的行为比较困难,这种情况下,需要定义Adaptee的子类来实现重定义,然后让适配器组合子类。虽然重定义Adaptee的行为比较困难,但是想要增加一些新的行为则方便的很,而且新增加的行为可同时适用于所有的源。

  • 对于类适配器,仅仅引入了一个对象,并不需要额外的引用来间接得到Adaptee。

  • 对于对象适配器,需要额外的引用来间接得到Adaptee。

  • 建议尽量使用对象适配器的实现方式,多用合成/聚合、少用继承。当然,具体问题具体分析,根据需要来选用实现方式,最适合的才是最好的。

适配器模式的优点

  • 将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,而无须修改原有代码。

  • 增加了类的透明性和复用性,将具体的实现封装在适配者类中,对于客户端类来说是透明的,而且提高了适配者的复用性。

  • 灵活性和扩展性都非常好,通过使用配置文件,可以很方便地更换适配器,也可以在不修改原有代码的基础上增加新的适配器类,完全符合“开闭原则”。

类适配器模式还具有如下优点:

  • 由于适配器类是适配者类的子类,因此可以在适配器类中置换一些适配者的方法,使得适配器的灵活性更强。

对象适配器模式还具有如下优点:

  • 一个对象适配器可以把多个不同的适配者适配到同一个目标,也就是说,同一个适配器可以把适配者类和它的子类都适配到目标接口。

适配器模式的缺点

类适配器模式的缺点如下:

  • 对于Java、C#等不支持多重继承的语言,一次最多只能适配一个适配者类,而且目标抽象类只能为抽象类,不能为具体类,其使用有一定的局限性,不能将一个适配者类和它的子类都适配到目标接口。

对象适配器模式的缺点如下:

  • 与类适配器模式相比,要想置换适配者类的方法就不容易。如果一定要置换掉适配者类的一个或多个方法,就只好先做一个适配者类的子类,将适配者类的方法置换掉,然后再把适配者类的子类当做真正的适配者进行适配,实现过程较为复杂。

代码已经放到GitHub上了https://github.com/HJXANDHMR/DesignPattern

参考
http://design-patterns.readthedocs.io/zh_CN/latest/structural_patterns/adapter.html
http://www.cnblogs.com/java-my-life/archive/2012/04/13/2442795.html

欢迎大家关注我的微信公众号,我会不定期的分享些Android开发的技巧

文章目录
  1. 1. 模式定义
  2. 2. 模式结构
  3. 3. UML图
    1. 3.1. 类适配器UML图
    2. 3.2. 对象适配器UML图
  4. 4. 类适配器模式代码实现
    1. 4.1. Target.java
    2. 4.2. Adaptee.java
    3. 4.3. Adapter.java
    4. 4.4. 测试类
    5. 4.5. 运行结果
  5. 5. 对象适配器代码实现
    1. 5.1. Target.java
    2. 5.2. Adaptee.java
    3. 5.3. Adapter.java
    4. 5.4. 测试类
    5. 5.5. 运行结果
  6. 6. 模式分析
  7. 7. 适配器模式的优点
  8. 8. 适配器模式的缺点