zoukankan      html  css  js  c++  java
  • Laravel5.1学习笔记13 系统架构5 Contract

    Contract

    简介

    Laravel 中的 Contract 是一组定义了框架核心服务的接口。例如,IlluminateContractsQueueQueue contract 定义了实现队列任务所需实现的方法,而 IlluminateContractsMailMailer contract 定义了发送邮件所需要实现的方法。

    框架为每个 contract 都提供了一个相对应的实现。例如,Laravel 为队列提供了各种驱动的实现,以及基于 SwiftMailer 对邮件功能的实现。

    Laravel 所自带的所有 contract 都有自己的 GitHub 仓库。除了方便列出所有可用的 contract 外,也可以作为独立、解耦的工具包供其他开发者使用。

    Contract Vs. Facade

    Laravel 中的 facades 提供了一个简单的方法来使用 Laravel 自带的服务(service),而不需要使用使用类型提示(type-hint)和在服务容器(service container)之外解析 contract。然而,使用 contract 可以明确地为类定义其依赖。对于大部分应用程序而放眼,使用 facade 就足够了。然而,如果你需要更多的低耦合,contract 就适合你了,你可以继续往下看了解更多!

    为什么使用 Contract ?

    你可能对于 contract 还有很多疑问。为什么要使用接口(interface)?使用接口会不会更复杂了?接下来列出的两个标题能够解释这个问题:低耦合和简单性。

    低耦合

    首先,我们来看一下这段和缓存功能的实现具有强耦合的代码。如下:

    <?php

    namespace AppOrders;

    class Repository
    {
    /**
    * The cache.
    */
    protected $cache;

    /**
    * Create a new repository instance.
    *
    * @param SomePackageCacheMemcached $cache
    * @return void
    */
    public function __construct(SomePackageCacheMemcached $cache)
    {
    $this->cache = $cache;
    }

    /**
    * Retrieve an Order by ID.
    *
    * @param int $id
    * @return Order
    */
    public function find($id)
    {
    if ($this->cache->has($id)) {
    //
    }
    }
    }

    在这个类中,代码和缓存功能的实现之间是强耦合的。因为它依赖第三方工具包中定义的缓存类。如果这个第三方工具包的 API 改变了,我们的代码也要跟着变。

    同样的,如果我们希望用另一项技术(Redis)来替换掉现在所用的(Memcached),我们必须修改代码。我们所定义的类不应该依赖是谁提供了数据以及如何提供的等等细节。

    比起上面代码中的做法,我们的代码应该依赖一个简单、不依赖第三方实现细节的接口:

    <?php

    namespace AppOrders;

    use IlluminateContractsCacheRepository as Cache;

    class Repository
    {
    /**
    * Create a new repository instance.
    *
    * @param Cache $cache
    * @return void
    */
    public function __construct(Cache $cache)
    {
    $this->cache = $cache;
    }
    }

    现在,上面的代码已经不再和具体的第三方代码甚至是 Laravel 有任何耦合了。由于 contract 工具包不包含任何实现,也不依赖其他工具包,你可以很方便地为任何 contract 创造一个实现,甚至在不需要修改任何涉及到调用缓存的代码的情况下替换为你自己的缓存实现。

    简单性

    当所有的 Laravel 服务(service)都通过简洁的接口进行定义,就能够很容易地确定这个服务提供的是什么功能了。可以将 contract 视为框架所提供的简洁明了的说明文档。

    另外,当你依赖一个简单清晰的接口时,你的代码能够被别人轻松的理解并维护。比起在一个冗长、复杂的类中追踪哪些方法可用来说,你所面对的将是一个简洁、干净的接口。

    Contract 索引

    下面列出的是大部分 Laravel Contract 的索引文件,以及对应的 "facade" :

    Contract 对应的Facade
    IlluminateContractsAuthGuard Auth
    IlluminateContractsAuthPasswordBroker Password
    IlluminateContractsBusDispatcher Bus
    IlluminateContractsBroadcastingBroadcaster  
    IlluminateContractsCacheRepository Cache
    IlluminateContractsCacheFactory Cache: driver()
    IlluminateContractsConfigRepository Config
    IlluminateContractsContainerContainer App
    IlluminateContractsCookieFactory Cookie
    IlluminateContractsCookieQueueingFactory Cookie::queue()
    IlluminateContractsEncrptionEncrypter Crypt
    IlluminateContractsEventsDispatcher Event
    IlluminateContractsFilesystemCloud  
    IlluminateContractsFilesystemFactory File
    IlluminateContractsFilesystemFilesystem File
    IlluminateContractsFoundationApplication App
    IlluminateContractsHashingHasher Hash
    IllluminateContractsLoggingLog Log
    IlluminateContractsMailMailQueue Mail::queue()
    IlluminateContractsqueueFactory Queue:: driver()
    IlluminateContractsQueueQueue Queue
    IlluminateContractsRedisDatabase Redis
    IlluminateContractsRoutingRegistar Route
    IlluminateContracts/RoutingResponsefactory Response
    IlluminateContractsRoutingUrlGenerator URL
    IlluminateContractsSupportArrayable  
    IlluminateContractsSupportJsonable  
    IlluminateContractsSupportRenderable  
    IlluminateContractsValidationFactory Validator::make()
    IlluminateContractsValidationValidator  
    IlluminateContractsViewFactory View::make()
    IlluminateContractsViewView  

     

     

    如何使用 Contract

    那么,如何实例化一个 contract 呢?其实很简单。

    Laravel 中的很多类都是由 服务容器 来解析的,包括控制器、事件监听器、中间件、队列任务,甚至路由闭包(route closure)。因此,要实例化一个 contract,你可以在,类的构造函数中加入“类型提示(type-hint)”。

    例如,请看下面的事件监听器:

    <?php

    namespace AppListeners;

    use AppUser;
    use AppEventsNewUserRegistered;
    use IlluminateContractsRedisDatabase;

    class CacheUserInformation
    {
    /**
    * The Redis database implementation.
    */
    protected $redis;

    /**
    * Create a new event handler instance.
    *
    * @param Database $redis
    * @return void
    */
    public function __construct(Database $redis)
    {
    $this->redis = $redis;
    }

    /**
    * Handle the event.
    *
    * @param NewUserRegistered $event
    * @return void
    */
    public function handle(NewUserRegistered $event)
    {
    //
    }
    }

    当事件监听器被解析的时候,服务容器将会读取构造函数的类型提示(type-hint),并注入适当的值。关于如何向服务容器注册,请参考此文档

  • 相关阅读:
    Java Web(5) Spring 下使用Junit4 单元测试
    聊聊单元测试(三)——Spring Test+JUnit完美组合
    浅谈ELK日志分析平台
    ELK 实现 Java 分布式系统日志分析架构
    ELK(ElasticSearch, Logstash, Kibana)搭建实时日志分析平台
    开源分布式搜索平台ELK(Elasticsearch+Logstash+Kibana)入门学习资源索引
    自动补全下拉框(可输入匹配的下拉框)
    这是一篇满载真诚的微信小程序开发干货
    微服务化的多组件项目,跨地域、分布式版本管理和发布方式
    解放双手,发掘更大的价值:智能化运维
  • 原文地址:https://www.cnblogs.com/grkin/p/4610636.html
Copyright © 2011-2022 走看看