设计模式 | 适配器模式

说明

适配器模式(adapter), 模式定义: 将一个类的接口转换成客户希望的另一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作

从名字可以知道, 是为了适配不兼容的东西而产生, 我们电脑可能充电需要200v的电压, 但是有一天换了个充电的是300v的, 和电脑原本不兼容, 这个时候就会有适配器来帮我们转化

例如说有个场景:

我们公司内部有一套用户系统, 但是这个时候和其他公司合作, 希望两边用户实现互通, 查询可以选择查我们这边 也可以查另一边, 但是两边数据结构不一样, 在页面不可能做处理, 这个时候就需要转化成我们想要的格式, 这中间这些转化操作抽离出来叫适配器。

实现如下:

示例


<?php
/**
 * Created by 憧憬.
 */

interface IUserInfo {
    public function getUsername();
    public function getHomeAddress();
    public function getMobileNumber();
    public function getJobPosition();
    public function getOfficeTelNumber();
    public function getHomeTelNumber();
}


class UserInfo implements IUserInfo {
    public function getUsername()
    {
        echo 'user name';
        return null;
    }

    public function getHomeAddress()
    {
        echo 'getHomeAddress';
        return null;
    }

    public function getMobileNumber()
    {
        echo 'getMobileNumber';
        return null;
    }

    public function getJobPosition()
    {
        echo 'getJobPosition';
        return null;
    }

    public function getOfficeTelNumber()
    {
        echo 'getOfficeTelNumber';
        return null;
    }

    public function getHomeTelNumber()
    {
        echo 'getHomeTelNumber';
        return null;
    }
}


/**
 * 外部用户系统接口
 * Interface IOuterUser
 */
interface IOuterUser {

    //基本信息,比如名称,性别,手机号码了等
    public function getUserBaseInfo();

    //工作区域信息
    public function getUserOfficeInfo();

    //用户的家庭信息
    public function getUserHomeInfo();
}


/**
 * 外部用户系统实现类
 * Class OuterUser
 */
class OuterUser implements IOuterUser {

    /**
     * 用户的基本信息
     * @return array
     * @author: 憧憬
     */
    public function getUserBaseInfo()
    {
        $arr = [
            'userName' => '这个员工叫混世魔王..',
            'mobileNumber' => '这个员工电话是...',
        ];

        return $arr;
    }

    /**
     * 员工的工作信息,比如职位了等
     * @return array
     * @author: 憧憬
     */
    public function getUserOfficeInfo()
    {
        $arr = [
            'jobPosition' => '这个人的职位是BOSS...',
            'officeTelNumber' => '员工的办公电话是....',
        ];

        return $arr;
    }

    /**
     * 员工的家庭信息
     * @return array
     * @author: 憧憬
     */
    public function getUserHomeInfo()
    {
        $arr = [
            'homeTelNumbner' => '员工的家庭电话是.....',
            'homeAddress' => '员工的家庭地址是....',
        ];

        return $arr;
    }
}


// 那怎么把外系统的用户信息包装成我们公司的人员信息呢?

class OuterUserInfo extends OuterUser implements IUserInfo {

    private $baseInfo;
    private $homeInfo;
    private $officeInfo;

    /**
     * OuterUserInfo constructor.
     */
    public function __construct()
    {
        $this->baseInfo = parent::getUserBaseInfo();
        $this->homeInfo = parent::getUserHomeInfo();
        $this->officeInfo = parent::getUserOfficeInfo();
    }


    public function getUsername()
    {
        return $this->baseInfo['userName'];
    }

    public function getHomeAddress()
    {
        return $this->homeInfo['homeAddress'];
    }

    public function getMobileNumber()
    {
        return $this->baseInfo['mobileNumber'];
    }

    public function getJobPosition()
    {
        return $this->officeInfo['jobPosition'];
    }

    public function getOfficeTelNumber()
    {
        return $this->officeInfo['officeTelNumber'];
    }

    public function getHomeTelNumber()
    {
        return $this->homeInfo['homeTelNumbner'];
    }
}

// 选择查询

//$user = new UserInfo();
$user = new OuterUserInfo();

// 查询用户
for ($i = 0; $i< 100; $i++) {
    echo $user->getMobileNumber();
}


使用了适配器模式只修改了一句话,其他的业务逻辑都不用修改就解决了系统对接的问题, 而且在我们实际系统中只是增加了一个业务类的继承,就实现了可以查本公司的员工信息,也可以查人力 资源公司的员工信息,尽量少的修改,通过扩展的方式解决了该问题。

适配器还分为类适配器和对象适配器,这种是类适配器模式, 这种直接继承的方式不是很好, 耦合比较高, 其实可以改为组合模式, 不使用继承, 将OuterUser实例传入, 这样代码就不会相互影响了,大家可以好好去尝试一下。

本文为作者原创,手码不易,允许转载,转载后请以链接形式说明文章出处。

您的支持是对我最大的鼓励!

发表于: 作者:憧憬。
关注互联网以及分享全栈工作经验的原创个人博客和技术博客,热爱编程,极客精神
Github 新浪微博 SegmentFault 掘金专栏