跳到主要内容

PHP 适配器模式

什么是适配器模式?

适配器模式(Adapter Pattern)是一种结构型设计模式,它允许不兼容的接口之间进行协作。简单来说,适配器模式就像是一个“转换器”,它可以将一个类的接口转换成客户端期望的另一个接口,从而使原本不兼容的类能够一起工作。

适配器模式通常用于以下场景:

  • 当你需要使用一个现有的类,但其接口与你的代码不兼容时。
  • 当你希望创建一个可复用的类,该类可以与不相关或不可预见的类协同工作。

适配器模式的实现

适配器模式有两种常见的实现方式:

  1. 类适配器:通过继承来实现适配器。
  2. 对象适配器:通过组合来实现适配器。

类适配器

类适配器通过继承目标类和适配者类来实现适配。以下是一个简单的类适配器示例:

php
<?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 接口,从而将 AdapteespecificRequest 方法适配为 Target 接口的 request 方法。

对象适配器

对象适配器通过组合适配者类来实现适配。以下是一个对象适配器的示例:

php
<?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
<?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)创建适配器,使它们能够以统一的接口被调用。
  • 进一步阅读:了解其他结构型设计模式,如装饰器模式、代理模式等,并思考它们与适配器模式的区别和联系。
提示

适配器模式的核心思想是“转换接口”,而不是改变原有功能。在设计适配器时,尽量保持原有功能不变,只进行接口的适配。