为什么用 Contracts
最后更新于:2022-04-01 15:05:03
你可能有很多关于 contracts 的问题。如为什么要使用接口?使用接口会不会变的更复杂?
让我们用下面的标题来解释为什么要使用接口:低耦合和简单性。
低耦合
首先,看一些强耦合的缓存实现代码。如下:
~~~
<?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))
{
//
}
}
}
~~~
在上面的类里,代码跟缓存实现之间是强耦合。理由是它会依赖于扩展包库( package vendor )的特定缓存类。一旦这个扩展包的 API 更改了,我们的代码也要跟着改变。
同样的,如果想要将底层的缓存技术(比如 Memcached )抽换成另一种(像 Redis ),又一次的我们必须修改这个 repository 类。我们的 repository 不应该知道这么多关于谁提供了数据,或是如何提供等等细节。
比起上面的做法,我们可以改用一个简单、和扩展包无关的接口来改进代码:
~~~
<?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。既然 contracts 扩展包没有包含实现和任何依赖,你可以很简单的对任何 contract 进行实现,你可以很简单的写一个替换的实现,甚至是替换 contracts,让你可以替换缓存实现而不用修改任何用到缓存的代码。
简单性
当所有的 Laravel 服务都简洁的使用简单的接口定义,就能够很简单的决定一个服务需要提供的功能。** 可以将 contracts 视为说明框架特色的简洁文档。
除此之外,当你依赖简洁的接口,你的代码能够很简单的被了解和维护。比起搜索一个大型复杂的类里有哪些可用的方法,你有一个简单,干净的接口可以参考。