Contract

简介

Laravel 中的 Contract 是一组定义了框架核心服务的接口。例如,Illuminate\Contracts\Queue\Queue contract 定义了实现队列任务所需实现的方法,而 Illuminate\Contracts\Mail\Mailer 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 App\Orders;

class Repository
{
/**
* The cache.
*/
protected $cache; /**
* Create a new repository instance.
*
* @param \SomePackage\Cache\Memcached $cache
* @return void
*/
public function __construct(\SomePackage\Cache\Memcached $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 App\Orders;

use Illuminate\Contracts\Cache\Repository 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
Illuminate\Contracts\Auth\Guard Auth
Illuminate\Contracts\Auth\PasswordBroker Password
Illuminate\Contracts\Bus\Dispatcher Bus
Illuminate\Contracts\Broadcasting\Broadcaster  
Illuminate\Contracts\Cache\Repository Cache
Illuminate\Contracts\Cache\Factory Cache: driver()
Illuminate\Contracts\Config\Repository Config
Illuminate\Contracts\Container\Container App
Illuminate\Contracts\Cookie\Factory Cookie
Illuminate\Contracts\Cookie\QueueingFactory Cookie::queue()
Illuminate\Contracts\Encrption\Encrypter Crypt
Illuminate\Contracts\Events\Dispatcher Event
Illuminate\Contracts\Filesystem\Cloud  
Illuminate\Contracts\Filesystem\Factory File
Illuminate\Contracts\Filesystem\Filesystem File
Illuminate\Contracts\Foundation\Application App
Illuminate\Contracts\Hashing\Hasher Hash
Illluminate\Contracts\Logging\Log Log
Illuminate\Contracts\Mail\MailQueue Mail::queue()
Illuminate\Contracts\queue\Factory Queue:: driver()
Illuminate\Contracts\Queue\Queue Queue
Illuminate\Contracts\Redis\Database Redis
Illuminate\Contracts\Routing\Registar Route
Illuminate\Contracts/Routing\Responsefactory Response
Illuminate\Contracts\Routing\UrlGenerator URL
Illuminate\Contracts\Support\Arrayable  
Illuminate\Contracts\Support\Jsonable  
Illuminate\Contracts\Support\Renderable  
Illuminate\Contracts\Validation\Factory Validator::make()
Illuminate\Contracts\Validation\Validator  
Illuminate\Contracts\View\Factory View::make()
Illuminate\Contracts\View\View  

 

 

如何使用 Contract

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

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

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

<?php

namespace App\Listeners;

use App\User;
use App\Events\NewUserRegistered;
use Illuminate\Contracts\Redis\Database; 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),并注入适当的值。关于如何向服务容器注册,请参考此文档

Laravel5.1学习笔记13 系统架构5 Contract的更多相关文章

  1. Laravel5.1学习笔记i14 系统架构6 Facade

    Facades 介绍  使用 Facades Facade 类参考   #介绍 Facades provide a "static" interface to classes th ...

  2. Laravel5.1学习笔记12 系统架构4 服务容器

    Service Container 介绍 绑定的用法  绑定实例到接口 上下文绑定 标签 解析 容器事件 #介绍 The Laravel service container is a powerful ...

  3. Laravel5.1学习笔记11 系统架构3 服务提供者

    服务提供者 简介 写一个服务提供者 Register注册方法 Boot 方法 注册提供者 缓载提供者 简介 Service providers are the central place of all ...

  4. Laravel5.1学习笔记10 系统架构2 应用程序结构

    应用程序结构 简介 根目录 App 目录 为应用程序设置命名空间 简介 默认的 Laravel 应用程序结构是为了给无论构建大型还是小型应用程序都提供一个良好的开始.当然,你可以依照喜好自由地组织应用 ...

  5. Laravel5.1学习笔记9 系统架构1 请求生命周期 (待修)

    Request Lifecycle Introduction Lifecycle Overview Focus On Service Providers Introduction When using ...

  6. ODI学习笔记2--ODI产品架构

    ODI学习笔记2--ODI产品架构 ODI产品架构: ODI提供了以下几种管理工具:Designer 用于定义数据转换逻辑,这是最常用的开发工具,大部分的开发任务,包括data store的定义,in ...

  7. SQL反模式学习笔记13 使用索引

    目标:优化性能 改善性能最好的技术就是在数据库中合理地使用索引.  索引也是数据结构,它能使数据库将指定列中的某个值快速定位在相应的行. 反模式:无规划的使用索引 1.不使用索引或索引不足 2.使用了 ...

  8. springmvc学习笔记(13)-springmvc注解开发之集合类型參数绑定

    springmvc学习笔记(13)-springmvc注解开发之集合类型參数绑定 标签: springmvc springmvc学习笔记13-springmvc注解开发之集合类型參数绑定 数组绑定 需 ...

  9. Ext.Net学习笔记13:Ext.Net GridPanel Sorter用法

    Ext.Net学习笔记13:Ext.Net GridPanel Sorter用法 这篇笔记将介绍如何使用Ext.Net GridPanel 中使用Sorter. 默认情况下,Ext.Net GridP ...

随机推荐

  1. 【02】Node.js 安装配置(OK)

    [02] Node.js 安装配置 本章节我们将向大家介绍在window和Linux上安装Node.js的方法. Node.js安装包及源码下载地址为:http://www.nodejs.org/do ...

  2. Maven学习总结(29)——Maven项目的pom.xml中log4j2配置

        <dependency>         <groupId>org.apache.logging.log4j</groupId>         <a ...

  3. RabbitMQ-高级特性(六)

    存储机制 待... 消息结构 惰性队列 惰性队列会尽可能将消息存入到磁盘中,消费者消费相应的消息才会加载到内存,它可以支持更长的队列 默认情况下生产者消息会尽可能存储到内存中就算设置持久化消息 也会再 ...

  4. mysql执行show processlist unauthenticated user 解决方法

    一台unibilling机器前几天突然负载变重. 在top中发现cpu被大量占用. agi程序运行的很慢,并出现僵尸进程. 其实当时只有50个左右的并发呼叫. 远远达不到正常水准. 重新启动机器问题也 ...

  5. kafka+spark-streaming实时推荐系统性能优化笔记

    1) --conf spark.dynamicAllocation.enabled=false 如果正在使用的是CDH的Spark,修改这个配置为false:开源的Spark版本则默认是false. ...

  6. 21、Java并发性和多线程-Java中的锁

    以下内容转自http://ifeve.com/locks/: 锁像synchronized同步块一样,是一种线程同步机制,但比Java中的synchronized同步块更复杂.因为锁(以及其它更高级的 ...

  7. 使用系统存储过程来监控SQLServer进程和会话具体解释

     承接上文,本文讲述怎样使用系统存储过程来监控系统. SQLServer相同也提供了一系列系统存储过程用于监控SQLServer,获取当前进程.会话.请求以及锁定的具体信息.本文将演示系统存储过程 ...

  8. nginx + mysql + php-fpm 环境

    安装 Nginx 想在 CentOS 系统上安装 Nginx ,你得先去加入一个资源库.像这样: vim /etc/yum.repos.d/nginx.repo 使用 vim 命令去打开 /etc/y ...

  9. Unity学习笔记(4) --- Unity的界面排版:初识GUI

    GUI和GUILayout是Unity提供的UIKit.在使用GUI的Controls时都要求设置Rect參数.没办法做到自己主动排版,给适配带来难度.而GUILayout的设计就是为了弥补这个缺陷, ...

  10. 我的Go语言学习之旅七:创建一个GUI窗口

    在上次中,刚刚学过了  弹窗效果.这里再接着学习一下怎样创建一个窗口. 还是老路子,先上代码: package main import ( "github.com/lxn/go-winapi ...