愿你坚持不懈,努力进步,进阶成自己理想的人

—— 2017.09, 写给3年后的自己

设计模式之适配器模式

一、使用场景

记得我初中的时候,用压岁钱买了台NDSi,很是高兴,那时候市面上大部分的游戏机都是进口的水货(如日版、美版、欧版),而我所买的版本就是日版的NDSi。然后遇到了一个问题,日本的电压是110V,因而日版NDSi自带的充电电源也是110V范围内的,而我国的电压都是220V,这种情况下,就有人发明出了“火牛”这东西,将110V的电源插在火牛上,火牛再插在220V的插座上,就解决了电压不合适的问题,而火牛在这里充当的角色就是适配器。由此引申,适配器模式主要是解决希望能够复用一个现有的类,但是复用环境下又不能直接使用现有类的问题。

二、角色

  • 需要适配的类Adaptee
  • 适配器Adapter
  • 目标接口Target

三、实现

1、首先,我们需要一个不能直接使用的,需要我们适配的类,假设是日本标准的电源,所以Adaptee为:

class JPPower {
    public function chargeWith110V() {
        echo "充电中...";
    }
}

2、我们没办法使用这个日本标准的电源,在国内要用的,是符合220V电压标准的电源,所以Target为:

interface CNPower {
    public function chargeWith220V();
}

3、为了满足转化要求,我们需要一个火牛(电源适配器):

class Adapter implements CNPower {
    private $adaptee;

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

    public function chargeWith220V() {
        $this->adaptee->chargeWith110V();
    }
}

4、好了,有了以上的准备工作,我们就可以开始充电,然后愉快地玩马里奥了。因为PHP多态的特征比较不明显,为了明显一点,我们使用类型约束来演示下,如下:

class PlayNDSi {
    public static function chargeTo(CNPower $power) {
        $power->chargeWith220V();
    }
}

PlayNDSi::chargeTo(new Adapter());

// 运行结果:充电中...