初识设计模式——适配器模式(Adapter Pattern)

cuixiaogang

适配器模式(Adapter Pattern)是一种结构型设计模式,其主要作用是让原本因接口不兼容而无法一起工作的类能够协同工作。它就像一个转换器,将一个类的接口转换成客户希望的另一个接口。

适配器模式的构成

  • 目标接口(Target):定义了客户端期望使用的接口,是客户端最终调用的接口。
  • 适配者类(Adaptee):已存在的、需要被适配的类,它有自己的接口和实现,但与目标接口不兼容。
  • 适配器类(Adapter):该类实现了目标接口,并且持有适配者类的实例,负责将目标接口的方法调用转换为适配者类的方法调用。

适配器模式结构图

案例

场景分析

在 Web 开发中,假设我们有一个旧的用户信息管理系统,它使用 getUserInfoOld 方法获取用户信息,返回的是一个数组。而新的系统需要使用一个对象来表示用户信息,并且调用 getUserInfoNew 方法。我们可以使用适配器模式来解决这个问题。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<?php
// 目标接口
interface UserInfoInterface {
public function getUserInfoNew();
}

// 适配者类
class OldUserInfoSystem {
public function getUserInfoOld() {
return [
'name' => 'John Doe',
'age' => 30,
'email' => 'johndoe@example.com'
];
}
}

// 适配器类
class UserInfoAdapter implements UserInfoInterface {
private $oldSystem;

public function __construct(OldUserInfoSystem $oldSystem) {
$this->oldSystem = $oldSystem;
}

public function getUserInfoNew() {
$oldInfo = $this->oldSystem->getUserInfoOld();
$userInfo = new stdClass();
$userInfo->name = $oldInfo['name'];
$userInfo->age = $oldInfo['age'];
$userInfo->email = $oldInfo['email'];
return $userInfo;
}
}

// 客户端代码
$oldSystem = new OldUserInfoSystem();
$adapter = new UserInfoAdapter($oldSystem);
$newUserInfo = $adapter->getUserInfoNew();

echo "Name: ". $newUserInfo->name. "\n";
echo "Age: ". $newUserInfo->age. "\n";
echo "Email: ". $newUserInfo->email. "\n";
?>

代码解释

  • UserInfoInterface 是目标接口。
  • OldUserInfoSystem 是适配者类。
  • UserInfoAdapter 是适配器类。
  • 客户端通过调用适配器的 getUserInfoNew 方法,获取到了符合新系统要求的用户信息对象。

UML类图

UML类图

适配器模式的适用场景

  • 系统需要使用现有的类,但这些类的接口与系统要求不兼容时:比如在整合旧系统和新系统时,旧系统的接口可能无法直接被新系统调用,这时就可以使用适配器模式进行适配。
  • 创建一个可复用的类,该类需要与一些彼此之间没有太大关联的类进行协同工作时:例如开发一个通用的工具类,需要适配不同格式的数据输入。

适配器模式的优缺点

优点

  • 提高了类的复用性:可以让原本不兼容的类一起工作,避免了对现有类的修改,提高了代码的复用性。
  • 增加了类的透明度:客户端只需要和目标接口交互,不需要了解适配器内部的具体实现,降低了客户端与适配者类之间的耦合度。
  • 灵活性和扩展性好:可以很方便地添加新的适配器类,以适应不同的适配者类。

缺点

  • 过多使用适配器会使系统变得复杂:如果系统中存在大量的适配器,会增加系统的理解和维护难度。