专栏首页进击的程序猿The Clean Architecture in PHP 读书笔记(五)The Clean Architecture in PHP 读书笔记(五)

The Clean Architecture in PHP 读书笔记(五)The Clean Architecture in PHP 读书笔记(五)

interface

上篇最重要的是介绍了去耦的工具之一依赖注入,本篇将继续介绍去耦工具:接口和适配器,本文是The Clean Architecture in PHP的第5篇。

本文为系列文章的第五篇,前4篇地址是

The Clean Architecture in PHP 读书笔记(一)

The Clean Architecture in PHP 读书笔记(二)

The Clean Architecture in PHP 读书笔记(三)

The Clean Architecture in PHP 读书笔记(四)

The Clean Architecture in PHP 读书笔记(五)

先介绍接口原则,在介绍适配器。

通过接口来定义契约

前面几部分我们一直在讨论如何去耦这个主题,前篇最后我们的写出的代码如下:

class CustomerController {
    protected $repository;
    public function __construct( CustomerRepository $repo )
    {
        $this->repository = $repo;
    }
    public function viewAction()
    {
        $customer = $this->repository->getById( 1001 );
        return $customer;
    }
}

此处我们只是将对CustomerRepository从方法viewAction转移到了构造函数,整个类CustomerController还是对CustomerRepository有依赖,并且由于类CustomerRepository实现上是从数据库读取数据,意味着CustomerController还依赖于数据库。

因此我们需要对CustomerRepository在做一次抽象:接口。下面先介绍PHP中的接口。

PHP中的接口

interface Automobile {
    public function drive();
    public function idle();
    public function park();
}

任何实现该接口的类,都需要实现3个方法。

使用接口来做类型提示

PHP7后我们可以通过类型来对函数的输入输出做出约束,此时我们的CustomerController变为如下:

interface CustomerRepositoryInterface {
    public function getById( $id );
}

class CustomerController {
    protected $repository;
    public function __construct( CustomerRepositoryInterface $repo )
    {
        $this->repository = $repo;
    }
    public function viewAction()
    {
        $customer = $this->repository->getById( 1001 );
        return $customer;
    }
}

只要实现满足CustomerRepositoryInterface接口即可,我们不再关心数据源是数据库还是web了。

使用接口来定义契约

另一种思考接口的角度是:接口是一种契约,定义了使用方和提供方之间的契约,只要满足契约,就ok。

让第三方库符合契约

我们自己来实现接口非常简单,但是如果是第三方代码怎么办呢?这就是我们下面要介绍的适配器模式。

通过适配器进行抽象

接口帮我们能够彻底的去耦,不再依赖于具体实现,但是这些代码如果都是我们自己写的没问题,但是我们如果用到了第三方的库,那怎么办呢?

看下面的代码:

class AddressController extends AbstractController {
    protected $geocoder;
    public function __construct( BillsGeocoder $geocoder )
    {
        $this->geocoder = $geocoder;
    }
    public function validateAddressAction()
    {
        $address = $this->vars()->fromPost( 'address' );
        $isValid = $this->geocoder->geocode( $address ) !== false;
    }
}

我们使用Bill's Geocoder来进行位置验证,我们通过依赖注入的方式来注入BillsGeocoder,这很好,但是如果以后我们找到了更好的验证方式,我们不得不修改代码。此处的问题是我们强依赖于BillsGeocoder类,那怎么解决呢?

建立适配器

通过建立适配器,将第三方库包装起来,代码如下:

interface GeocoderInterface {
    public function geocode( $address );
}

class BillsGeocoderAdapter implements GeocoderInterface {
    protected $geocoder;
    public function __construct( BillsGeocoder $geocoder )
    {
        $this->geocoder = $geocoder;
    }
    public function geocode( $address )
    {
        return $this->geocoder->geocode( $address );
    }
}

class AddressController extends AbstractController {

    protected $geocoder;

    public function __construct( GeocoderInterface $geocoder )
    {
        $this->geocoder = $geocoder;
    }

    public function validateAddressAction()
    {
        $address = $this->vars()->fromPost( 'address' );
        $isValid = $this->geocoder->geocode( $address ) !== false;
    }
}

此处我们通过定义接口,声明了契约,通过适配器BillsGeocoderAdapter去除了核心逻辑对外部库的依赖,有效的进行了去耦。

怎么起作用?

通过使用适配器模式,我们能够很方便的替换或者升级第三方库,同时不影响我们核心应用的逻辑。

以上就是我们所有的去耦工具了,此处总结下,我们又5大去耦工具:

  • Design Patterns,A Primer
  • SOLID Design Principles
  • Depedency Injection
  • Defining a Contract with Interfaces
  • Abstracting with Adapters

其中第一个工具设计模式是在The Clean Architecture in PHP 读书笔记(二)中介绍的;

第二个SOLID设计模式是在The Clean Architecture in PHP 读书笔记(三)中介绍,

第三个依赖注入则是在The Clean Architecture in PHP 读书笔记(四)中介绍,

第四和五在本文中介绍了。

前面几篇介绍的这些都是为了下面将要展开的Clean Architecture做准备,下一篇将开始介绍最核心的Clean Architecture,非常激动!

这是The Clean Architecture in PHP的第五篇,你的鼓励是我继续写下去的动力,期待我们共同进步。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Say No to Loop!

    本文会介绍下Eloquent\Collection,这个是什么呢?这是我们平常使用Eloquent中get,all返回的结果集。

    zhuanxu
  • The Clean Architecture in PHP 读书笔记(三)The Clean Architecture in PHP 读书笔记(三)

    这5大原则最初是由Robert C. Martin提出,这些原则主要解决了下面两个问题:

    zhuanxu
  • The Clean Architecture in PHP 读书笔记(二)

    设计模式是对软件中通用问题的总结,有了设计模式,方便我们进行交流,譬如一说MVC,我们就知道是怎么回事了,不然我们必须巴拉巴拉一大堆话去描述,不易于传播、交流,...

    zhuanxu
  • 百度发布人工智能云平台“天智”,浙江省11个城市组成舆情大数据联盟 | 大数据24小时

    数据猿导读 百度推出基于云的人工智能平台“天智”;电商解决方案供应商洪海龙腾新三板募资1800万元,用于提升大数据处理能力;云计算大数据公司“国云科技”新三板挂...

    数据猿
  • springboot配置之Profile多环境支持

    Profile是spring对不同环境提供不同配置功能的支持,可以通过激活、指定参数等方式快速切换环境。

    绝命生
  • jquery 图片文件转base64 显示

    <input type="file" id="open-file" /> $("#open-file").on('change',function(){ ...

    庞小明
  • 为什么 spring 中,不支持 autowired 静态变量?

    因为静态变量是属于本身类的信息,当类加载器加载静态变量时,Spring 的上下文环境还没有被加载,所以不可能为静态变量绑定值。

    水货程序员
  • 【Spark篇】---Spark解决数据倾斜问题

    数据倾斜问题是大数据中的头号问题,所以解决数据清洗尤为重要,本文只针对几个常见的应用场景做些分析 。

    LhWorld哥陪你聊算法
  • Linux编程--地址计算

    在学习Matrix的ELF Hook的过程中,发现在查找Library基址指针的时候,对于指针的运算有一些疑惑,特此记录。

    None_Ling
  • Nodejs + WebSocket + Vue 实现多人聊天室WebIM功能 – 第二章

    在《Nodejs + WebSocket简单介绍及示例 - 第一章》中简单的介绍了,Nodejs + WebSocket的使用方法及作用,今天就用它来搭建一个简...

    Javanx

扫码关注云+社区

领取腾讯云代金券