PHP 适配器模式
什么是适配器模式?
适配器模式(Adapter Pattern)是一种结构型设计模式,它允许不兼容的接口之间进行协作。简单来说,适配器模式就像是一个“转换器”,它可以将一个类的接口转换成客户端期望的另一个接口,从而使原本不兼容的类能够一起工作。
适配器模式通常用于以下场景:
- 当你需要使用一个现有的类,但其接口与你的代码不兼容时。
- 当你希望创建一个可复用的类,该类可以与不相关或不可预见的类协同工作。
适配器模式的实现
适配器模式有两种常见的实现方式:
- 类适配器:通过继承来实现适配器。
- 对象适配器:通过组合来实现适配器。
类适配器
类适配器通过继承目标类和适配者类来实现适配。以下是一个简单的类适配器示例:
<?php
// 目标接口
interface Target {
public function request(): string;
}
// 适配者类
class Adaptee {
public function specificRequest(): string {
return "Specific request.";
}
}
// 类适配器
class ClassAdapter extends Adaptee implements Target {
public function request(): string {
return $this->specificRequest();
}
}
// 客户端代码
function clientCode(Target $target) {
echo $target->request();
}
$adapter = new ClassAdapter();
clientCode($adapter);
?>
输出:
Specific request.
在这个例子中,ClassAdapter
继承了 Adaptee
并实现了 Target
接口,从而将 Adaptee
的 specificRequest
方法适配为 Target
接口的 request
方法。
对象适配器
对象适配器通过组合适配者类来实现适配。以下是一个对象适配器的示例:
<?php
// 目标接口
interface Target {
public function request(): string;
}
// 适配者类
class Adaptee {
public function specificRequest(): string {
return "Specific request.";
}
}
// 对象适配器
class ObjectAdapter implements Target {
private $adaptee;
public function __construct(Adaptee $adaptee) {
$this->adaptee = $adaptee;
}
public function request(): string {
return $this->adaptee->specificRequest();
}
}
// 客户端代码
function clientCode(Target $target) {
echo $target->request();
}
$adaptee = new Adaptee();
$adapter = new ObjectAdapter($adaptee);
clientCode($adapter);
?>
输出:
Specific request.
在这个例子中,ObjectAdapter
通过组合 Adaptee
类来实现适配,而不是通过继承。这种方式更加灵活,因为它允许适配器与多个适配者类一起工作。
实际应用场景
适配器模式在实际开发中有很多应用场景。以下是一个常见的例子:
场景:集成第三方支付网关
假设你正在开发一个电子商务网站,并且需要集成多个第三方支付网关。每个支付网关都有不同的接口,但你的系统希望使用统一的接口来处理支付请求。这时,适配器模式就可以派上用场。
<?php
// 统一的支付接口
interface PaymentGateway {
public function pay(float $amount): string;
}
// 第三方支付网关A
class PaymentGatewayA {
public function makePayment(float $amount): string {
return "Payment of $amount processed by Gateway A.";
}
}
// 第三方支付网关B
class PaymentGatewayB {
public function processPayment(float $amount): string {
return "Payment of $amount processed by Gateway B.";
}
}
// 适配器A
class PaymentGatewayAAdapter implements PaymentGateway {
private $gateway;
public function __construct(PaymentGatewayA $gateway) {
$this->gateway = $gateway;
}
public function pay(float $amount): string {
return $this->gateway->makePayment($amount);
}
}
// 适配器B
class PaymentGatewayBAdapter implements PaymentGateway {
private $gateway;
public function __construct(PaymentGatewayB $gateway) {
$this->gateway = $gateway;
}
public function pay(float $amount): string {
return $this->gateway->processPayment($amount);
}
}
// 客户端代码
function processPayment(PaymentGateway $gateway, float $amount) {
echo $gateway->pay($amount) . "<br />";
}
$gatewayA = new PaymentGatewayA();
$adapterA = new PaymentGatewayAAdapter($gatewayA);
processPayment($adapterA, 100.00);
$gatewayB = new PaymentGatewayB();
$adapterB = new PaymentGatewayBAdapter($gatewayB);
processPayment($adapterB, 200.00);
?>
输出:
Payment of 100 processed by Gateway A.
Payment of 200 processed by Gateway B.
在这个例子中,我们通过适配器模式将不同的第三方支付网关接口统一为 PaymentGateway
接口,从而使系统能够以一致的方式处理不同的支付请求。
总结
适配器模式是一种非常有用的设计模式,它可以帮助我们在不修改现有代码的情况下,将不兼容的接口转换为兼容的接口。通过类适配器和对象适配器两种实现方式,我们可以灵活地应对不同的场景需求。
在实际开发中,适配器模式常用于集成第三方库、遗留代码或不同系统的接口。掌握适配器模式不仅能够提高代码的复用性,还能使系统更加灵活和可扩展。
附加资源与练习
- 练习:尝试为不同的第三方API(如天气API、地图API)创建适配器,使它们能够以统一的接口被调用。
- 进一步阅读:了解其他结构型设计模式,如装饰器模式、代理模式等,并思考它们与适配器模式的区别和联系。
适配器模式的核心思想是“转换接口”,而不是改变原有功能。在设计适配器时,尽量保持原有功能不变,只进行接口的适配。