天天看点

设计模式 - 适配器模式简介PHP 代码示例

简介

场景

  • 现实场景:国内电压是 220v,外国部分国家是 110v,如果去出差,会需要携带两个电源适配器,以应对这两种不同的电压。
  • 数据库场景:每种编程语言都需要支持多种数据库,通常会抽象一层数据库连接层,例如 Java 的 JDBC,PHP 的 PDO。数据库连接层对应用开发人员提供标准接口,屏蔽了数据库底层的差异。数据库提供的接口则是千差万别的。所以,数据库连接层又拆分为两层,一层对外提供服务,一层用于连接不同的数据库。
  • 具体代码场景:想使用一个已经完成的类,但是它的接口不符合需求。

假设已经有可以提供服务的目标类,客户类访问目标类时,发现其提供的接口不满足需求。此时在客户类和目标类中间加一层抽象,使不能直接交互的类可以一起工作。

定义一个包装类,包装不兼容接口的对象,这个包装类指的就是适配器(Adapter),它所包装的对象就是适配者(Adaptee),即被适配的类。

模式定义

将一个接口转换成客户希望的另一个接口,使接口不兼容的那些类可以一起工作。

模式特点

适配器模式包含四个角色:

Target:目标抽象类,定义接口标准,客户端可以直接调用

Adapter:适配器类,适配 Adaptee 与 Target,使其可以协同工作

Adaptee:适配者类,需要进行适配的接口

Client:客户类

适配器模式包括两种:

  • 类结构型适配器:继承关系,Adapter 同时继承 Target 和 Adaptee 类。
  • 对象结构型适配器:关联关系,Adapter 继承 Target,关联 Adaptee。
设计模式 - 适配器模式简介PHP 代码示例
设计模式 - 适配器模式简介PHP 代码示例

优点

  • 符合“开闭原则”,可以用配置文件方便地更换适配器
  • 解耦,通过引入一个适配器类来重用现有的适配者类

类适配器模式优点:

  • Adapter 是 Adaptee 的子类,因此可以在 Adapter 中置换一些 Adaptee 的方法,使得适配器的灵活性更强。

对象适配器模式优点:

  • 允许一个 Adapter 与多个 Adaptee 同时工作

缺点

类适配器模式的缺点:

  • 对于不支持多继承的语言,一次最多只能适配一个 Adaptee,其使用有一定的局限性,不能将 Adaptee 和它的子类都适配到目标接口。当我们想要匹配一个类以及所有它的子类时,类 Adapter 不能胜任工作。

对象适配器模式的缺点:

  • 重定义 Adaptee 的行为比较困难。

PHP 代码示例

类适配器模式

<?php

interface Target {
    public function query();
}

class Adapter extends Adaptee implements Target {
    public function del() {
        echo "can not delete<br/>";
    }
}

class Adaptee {
    public function query() {
        echo "Adaptee query<br/>";
    }
}

class Client {
    public function test() {
        $adapter = new Adapter();

        $adapter->query();
        $adapter->del();
    }
}

$c = new Client();
$c->test();
           

输出:

Adaptee query
can not delete
           

对象适配器模式

<?php

interface Target {
    public function query();
}

class Adapter implements Target {
    private $adaptee;

    public function __construct(Adaptee $adaptee) {
        $this->adaptee = $adaptee;
    }

    public function query() {
        echo $this->adaptee->query();
    }

    public function del() {
        echo "can not delete<br/>";
    }
}

class Adaptee {
    public function query() {
        echo "Adaptee query<br/>";
    }
}

class Client {
    public function test() {
        $adaptee = new Adaptee();
        $adapter = new Adapter($adaptee);

        $adapter->query();
        $adapter->del();
    }
}

$c = new Client();
$c->test();
           

输出:

Adaptee query
can not delete
           

继续阅读