Java设计模式—适配器模式

文章目录
  1. 1. 介绍
  2. 2. 结构
    1. 2.1. 类适配器
    2. 2.2. 对象适配器
      1. 2.2.1. 代码示例
    3. 2.3. 缺省适配器
      1. 2.3.1. 代码示例
  3. 3. 适配器模式使用注意事项

介绍

适配器模式将一个类的接口适配成用户所期待的。一个适配器通常允许因为接口不兼容而不能一起工作的类能够在一起工作,做法是将类自己的接口包裹在一个已存在的类中

结构

  • 目标(Target)角色:这就是所期待得到的接口
  • 源(Adapee)角色:现在需要适配的接口。
  • 适配器(Adaper)角色:适配器类是本模式的核心。适配器把源接口转换成目标接口。显然,这一角色不可以是接口,而必须是具体类。
类适配器
  • 采用继承的方式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 适配器Adapter继承自Adaptee,同时又实现了目标(Target)接口。
public class Adapter extends Adaptee implements Target {

/**
* 1.目标接口要求调用Request()这个方法名,但源类Adaptee没有方法Request()
*
* 2.但实际上Request()只是调用源类Adaptee的SpecificRequest()方法的内容
*
* 3.所以适配器只是将SpecificRequest()方法作了一层封装,封装成Target可以调用的Request()而已
*/
@Override
public void Request() {
this.SpecificRequest();
}

}
对象适配器
  • 采用对象组合方式
代码示例

假设在我们的系统中有一个已经存在的方法(Adaptee可以实现一个接口,也可以是一个对象类) Adaptee

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* 需要被适配的对象
*/
public class Adaptee {

/**
* 已经存在的方法
*/
public void specificRequest() {
// TODO 具体业务方法
}

}

由于已经存在的接口不能满足我们的需求,现在我们定义一个我们期望的目标接口 Target

1
2
3
4
5
6
7
8
9
/**
* 目标接口
*/
public interface Target {
/**
* 目标方法
*/
void request();
}

定义适配器 Adapter ,进行适配 Adaptee

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* 适配器类
*/
public class Adapter implements Target {

/**
* 持有需要被适配的接口对象
*/
private Adaptee adaptee;

/**
* 传入需要被适配的对象
* @param adaptee
*/
public Adapter(Adaptee adaptee) {
this.adaptee = adaptee;
}

@Override
public void request() {
// 新接口中,调用的是已经存在的方法
adaptee.specificRequest();
}
}

测试代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Client {

public static void main(String[] args) {

// 创建需要被适配的对象
Adaptee adaptee = new Adaptee();

// 创建客户端需要调用的接口对象
Target target = new Adapter(adaptee);

// 表面上调用的是自己的新定义的接口,其内部实现还是原有的方法
target.request();
}
}
缺省适配器

 在任何时候,如果不准备实现一个接口的所有方法时,就可以使用“缺省适配模式”制造一个抽象类,给出所有方法的默认空实现。这样,从这个抽象类再继承下去的子类就不必实现所有的方法了

代码示例

定义一个动物 Animal 行为的接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public interface Animal {

/**
* 游泳
*/
void swim();

/**
* 睡觉
*/
void sleep();

/**
* 飞翔
*/
void fly();
}

我们知道麻雀只能飞翔,睡觉,但是不能在水里游泳;如我我们直接定义一个麻雀(Bird)类直接去实现动物(Animal)这个接口,那么 Animal 中游泳的方法我们也必须去实现 (这是接口的特性所导致),为了解决这个问题,我们定义一个抽象类作为适配器的角色来解决这个问题

适配器类 Adapter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public  abstract  class Adapter  implements Animal {
@Override
public void swim() {
// 空实现
}

@Override
public void sleep() {
// 空实现
}

@Override
public void fly() {
// 空实现
}
}

接下来我们定义麻雀类(Bird) 我们不直接实现接口(Animal),而是继承我们定义的适配器类 Adapter

1
2
3
4
5
6
7
8
9
10
11
public class Bird extends Adapter {
@Override
public void sleep() {
// TODO 业务实现
}

@Override
public void fly() {
// TODO 业务实现
}
}

适配器模式使用注意事项

  • 适配器模式中被适配的接口 Adaptee 和适配成为的接口 Target 是没有关联的,Adaptee 和 Target 中的方法既可以是相同的,也可以是不同的