PHP设计模式之适配器模式

适配器模式的英文翻译是 Adapter Design Pattern。顾名思义,这个模式就是用来做适配的,它将不兼容的接口转换为可兼容的接口,让原本由于接口不兼容而不能一起工作的类可以一起工作。对于这个模式,有一个经常被拿来解释它的例子,就是 USB 转接头充当适配器,把两种不兼容的接口,通过转接变得可以一起工作。

适配器模式有两种实现方式:类适配器和对象适配器。其中,类适配器使用继承关系来实现,对象适配器使用组合关系来实现。
适配器模式应用场景总结:

  • 1. 封装有缺陷的接口设计:假设我们依赖的外部系统在接口设计方面有缺陷(比如包含大量静态方法),引入之后会影响到我们自身代码的可测试性。为了隔离设计上的缺陷,我们希望对外部系统提供的接口进行二次封装,抽象出更好的接口设计,这个时候就可以使用适配器模式了。
  • 2. 统一多个类的接口设计:某个功能的实现依赖多个外部系统(或者说类)。通过适配器模式,将它们的接口适配为统一的接口定义,然后我们就可以使用多态的特性来复用代码逻辑。

假设系统要对用户输入的文本内容做敏感词过滤,为了提高过滤的召回率,我们引入了多款第三方敏感词过滤系统,依次对用户输入的内容进行过滤,过滤掉尽可能多的敏感词。但是,每个系统提供的过滤接口都是不同的。这就意味着我们没法复用一套逻辑来调用各个系统。这个时候就可以使用适配器模式,将所有系统的接口适配为统一的接口定义,可以复用调用敏感词过滤的代码。

  • 3. 替换依赖的外部系统:当我们把项目中依赖的一个外部系统替换为另一个外部系统的时候,利用适配器模式,可以减少对代码的改动。
  • 4. 兼容老版本接口:在做版本升级的时候,对于一些要废弃的接口,我们不直接将其删除,而是暂时保留,并且标注为 deprecated,并将内部实现逻辑委托为新的接口实现。这样做的好处是,让使用它的项目有个过渡期,而不是强制进行代码修改。
  • 5. 适配不同格式的数据:前面我们讲到,适配器模式主要用于接口的适配,实际上,它还可以用在不同格式的数据之 间的适配。比如,把从不同征信系统拉取的不同格式的征信数据,统一为相同的格式,以方便存储和使用。

假设有个业务场景:最早期是从mysql中查询数据,用到了Database类中的query()方法,而且这个query()方法被很多地方调用。然后有一天因为某些原因需要改成从redis查询数据,redis里面的方法名和mysql的方法有很大差别,又不想把所有被调用的地方的query()方法名都改一遍,这个时候就可以使用适配器模式,适配一个新的query()方法。

下面使用PHP代码实现这个场景。

query(); //从MySQL中查询数据

/**
 * 现在引入新的Redis操作数据类,里面的方法名和mysql的完全不同
 */
class RedisDatabase {
    public function hgetall() {
        echo "从Redis中获取数据" . PHP_EOL;
    }
}

/**
 * 创建一个适配器,适配原来mysql的query()方法
 */
class RedisAdapter extends Database {
    private $db;

    public function __construct(RedisDatabase $db) {
        $this->db = $db;
    }

    public function query() {
        $this->db->hgetall();
    }
}

//现在改成调用redis的操作数据类,调用的方法名还是 query()
$adatper = new RedisAdapter(new RedisDatabase());
$adatper->query(); //从Redis中获取数据

/**
 * 假如后面又需要改成MongoDB存储,可以再定义一个MongoDB的适配器即可
 */
class MongodbDatabase {
    public function findAll() {
        echo "从MongoDB中获取数据" . PHP_EOL;
    }
}

class MongodbAdapter extends Database {
    private $db;

    public function __construct(MongodbDatabase $db) {
        $this->db = $db;
    }

    public function query() {
        $this->db->findAll();
    }
}

$adatper = new MongodbAdapter(new MongodbDatabase());
$adatper->query(); //从MongoDB中获取数据

源代码:https://gitee.com/rxbook/php_design_pattern/blob/master/code11_adapter.php

你可能感兴趣的:(PHP设计模式,适配器模式,设计模式,php)