原文連接:learnku.com/laravel/t/4…
討論請前往專業的 Laravel 開發者論壇:learnku.com/Laravelphp
設計模式對每一個開發人員都很重要。它解決了您構建的每一個項目中很是常見的問題。laravel
它能夠幫助您在一個對象上添加額外的行爲,而又不影響同一類中的其餘對象。數據庫
裝飾器模式是一種設計模式,它容許動態地將行爲添加到單個對象,而不會影響同一類中其餘對象的行爲設計模式
假設咱們有一個Post模型緩存
class Post extends Model
{
public function scopePublished($query) {
return $query->where('published_at', '<=', 'NOW()');
}
}
複製代碼
在咱們的PostsController中,咱們有以下的index方法bash
class PostsController extends Controller
{
public function index() {
$posts = Post::published()->get();
return $posts;
}
}
複製代碼
爲了緩存帖子並避免每次咱們須要列出帖子時都查詢數據庫,咱們能夠執行如下操做app
class PostsController extends Controller
{
public function index() {
$minutes = 1440; # 1 day
$posts = Cache::remember('posts', $minutes, function () {
return Post::published()->get();
});
return $posts;
}
}
複製代碼
如今,咱們將帖子緩存1天。但看看代碼,控制器瞭解了太多。它知道咱們緩存了多少天,它本身緩存了對象。ide
一樣,假設您正在爲HomePageController的Tag,Category,Archives實現相同的功能。閱讀和維護的代碼太多了。post
在大多數狀況下,倉庫模式是鏈接到裝飾器模式。學習
首先,讓咱們使用倉庫模式分離獲取帖子的方式,建立具備如下內容的app/Repositories/Posts/PostsRepositoryInterface.php
namespace App\Repositories\Posts;
interface PostsRepositoryInterface
{
public function get();
public function find(int $id);
}
複製代碼
在同個目錄下建立具備下面內容的 PostsRepository
namespace App\Repositories\Posts;
use App\Post;
class PostsRepository implements PostsRepositoryInterface
{
protected $model;
public function __construct(Post $model) {
$this->model = $model;
}
public function get() {
return $this->model->published()->get();
}
public function find(int $id) {
return $this->model->published()->find($id);
}
}
複製代碼
回到PostsController並將更改應用爲
namespace App\Http\Controllers;
use App\Repositories\Posts\PostsRepositoryInterface;
use Illuminate\Http\Request;
class PostsController extends Controller
{
public function index(PostsRepositoryInterface $postsRepo) {
return $postsRepo->get();
}
}
複製代碼
控制器變得健康,知道足夠的細節來完成工做。
在這裏,咱們依靠 Laravel 的 IOC 注入 Posts 接口的具體對象來獲取咱們的帖子
咱們須要作的就是告訴Laravel的IOC使用接口時要建立哪一個類。
在你的 app/Providers/AppServiceProvider.php
添加綁定方法
namespace App\Providers;
use App\Repositories\Posts\PostsRepositoryInterface;
use App\Repositories\Posts\PostsRepository;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind(PostsRepositoryInterface::class,PostsRepository::class);
}
}
複製代碼
如今不管什麼時候咱們注入PostsRepositoryInterface
Laravel 都會建立 PostsRepository
的實例並將其返回。
咱們在一開始就說過,裝飾器模式容許將行爲添加到單個對象,而不會影響同一類中的其餘對象。
在這裏緩存是行爲,對象/類是 PostsRepository
。
讓咱們在 app/Repositories/Posts/PostsCacheRepository.php
中建立具備如下內容的PostsCacheRepository
namespace App\Repositories\Posts;
use App\Post;
use Illuminate\Cache\CacheManager;
class PostsCacheRepository implements PostsRepositoryInterface
{
protected $repo;
protected $cache;
const TTL = 1440; # 1 day
public function __construct(CacheManager $cache, PostsRepository $repo) {
$this->repo = $repo;
$this->cache = $cache;
}
public function get() {
return $this->cache->remember('posts', self::TTL, function () {
return $this->repo->get();
});
}
public function find(int $id) {
return $this->cache->remember('posts.'.$id, self::TTL, function () {
return $this->repo->find($id);
});
}
}
複製代碼
在這個類中,咱們接受 Caching 對象和 PostsRepository 對象,而後使用類(裝飾器)將緩存行爲添加到 PostsReposiory 實例。
咱們可使用相同的示例將HTTP請求發送到某些服務,而後在失敗的狀況下返回模型。我相信您會從該模式以及它是如何輕鬆添加行爲中受益。
最後一件事是修改 AppServiceProvider 接口綁定以建立 PostsCacheRepository 實例而不是PostsRepository
namespace App\Providers;
use App\Repositories\Posts\PostsRepositoryInterface;
use App\Repositories\Posts\PostsCacheRepository;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind(PostsRepositoryInterface::class,PostsCacheRepository::class);
}
}
複製代碼
如今再次檢查文件,您會發現它很是易於閱讀和維護。一樣,它也是可測試的,若是您決定在某個時候刪除緩存層。您只需在AppServiceProvider
中更改綁定便可。無需額外更改。
但願您喜歡閱讀本文。它向您展現了強大的設計模式,以及如何使您的項目易於維護和管理
原文連接:learnku.com/laravel/t/4…
討論請前往專業的 Laravel 開發者論壇:learnku.com/Larav