在 PHP 中,适配器模式通过将一个类的接口转换为另一个客户端期望的接口,使得不兼容的类能够协同工作。以下是具体实现步骤和示例:
1. 定义目标接口
声明客户端期望的接口方法:
interface DatabaseInterface {
public function query(string $sql): void;
}
2. 实现被适配的类(Adaptee)
假设有一个已存在的类,但其方法与目标接口不兼容:
class MysqlDatabase {
public function executeQuery(string $sql): void {
echo "执行 MySQL 查询: $sql\n";
}
}
3. 创建适配器类(Adapter)
适配器类实现目标接口,并内部调用被适配类的方法:
class MysqlAdapter implements DatabaseInterface {
private $mysql;
public function __construct(MysqlDatabase $mysql) {
$this->mysql = $mysql; // 组合方式持有被适配对象
}
public function query(string $sql): void {
$this->mysql->executeQuery($sql); // 转换接口调用
}
}
4. 客户端使用适配器
客户端通过目标接口与适配器交互,无需直接依赖被适配类:
// 被适配对象
$mysql = new MysqlDatabase();
// 适配器包装
$adapter = new MysqlAdapter($mysql);
// 客户端统一调用目标接口
$adapter->query("SELECT * FROM users");
场景扩展:参数转换
若接口参数不匹配,适配器可进行参数转换:
interface Calculator {
public function sum(array $numbers): int;
}
class LegacyCalculator {
public function add(int $a, int $b): int {
return $a + $b;
}
}
class LegacyAdapter implements Calculator {
private $legacy;
public function __construct(LegacyCalculator $legacy) {
$this->legacy = $legacy;
}
public function sum(array $numbers): int {
if (count($numbers) !== 2) {
throw new InvalidArgumentException("需两个参数");
}
return $this->legacy->add($numbers[0], $numbers[1]);
}
}
// 使用
$legacy = new LegacyCalculator();
$adapter = new LegacyAdapter($legacy);
echo $adapter->sum([10, 20]); // 输出 30
关键点
- 目标接口:定义客户端期望的规范。
- 适配器类:实现目标接口,内部持有被适配对象,并转换方法调用。
- 解耦:客户端仅依赖接口,无需关心具体实现。
- 灵活性:通过适配器兼容旧代码或第三方库,提升系统扩展性。
适配器模式在整合遗留代码、第三方库或统一多组件接口时非常实用。