您好,登錄后才能下訂單哦!
這篇文章主要介紹了Laravel面向接口編程的實現,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
面向接口編程是編碼中的一種設計思想,這種方式基于接口而不是固定的類來構建應用程序。
如果您是一名程序員,那么您可能聽說過則這樣的說法,例如:面向接口編程、使用抽象類代替固定類等等。
這些都是說的同一件事,編寫應用程序代碼時,使其依賴抽象接口而不是具體的類。
為什么?
這是我第一次聽到這句話時的確切反應。為什么要使用接口而不是類?即使創建了接口,我也需要創建一個實現該接口的類。這不是浪費時間嗎?
當然不是!!
這個世界上唯一不變的就是變化本身,也就是說,變化是永恒的。
就編程而言,這同樣沒有例外。業務需求隨著時間變化,我們的代碼也要隨之變化。
所以代碼必需保持靈活。
面向接口編程可以使代碼松散耦合且靈活。
怎么做?
觀察下面的代碼。
class Logger { public function log($content) { //日志保存到文件中. echo "Log to file"; } }
這是一個將日志記錄到文件的簡單類。 我們可以在控制器中調用它。
class LogController extends Controller { public function log() { $logger = new Logger; $logger->log('Log this'); } }
但如果需要將日志記錄到多個地方 (如數據庫,文件,云端等) 時,我們又該怎么辦呢。
然后我們可以更改 LogController 和 Logger 類以適應這些更改。
class Logger { public function logToDb($content) { //將日志記錄到 db. } public function logToFile($content) { //將日志保存到 file. } public function logToCloud($content) { //將日志存儲到 cloud. } }
class LogController extends Controller { public function log() { $logger = new Logger; $target = config('log.target'); if ($target == 'db') { $logger->logToDb($content); } elseif ($target == 'file') { $logger->logToFile($content); } else { $logger->logToCloud($content); } } }
現在我們可以記錄不同的目標了。但是,如果我們想將其他目標 (例如日志) 添加到 redis 服務器,該怎么辦?最后,我們將同時修改 Logger 類和 LogController 類。
如您所見,這很快就擺脫了我們的控制,并且代碼變得混亂。Logger 類很快成為一個整體。這是一場噩夢。
因此,我們需要拆分事物。遵循 SOLID 原則,我們可以將職責移至相應的類。
class DBLogger { public function log() { //將日志記錄到 db } } class FileLogger { public function log() { //將日志保存到 file } } class CloudLogger { public function log() { //將日志存儲到 cloud } }
并且控制器更改為:
class LogController extends Controller { public function log() { $target = config('log.target'); if ($target == 'db') { (new DBLogger)->log($content); } elseif ($target == 'file') { (new FileLogger)->log($content); } else { (new CloudLogger)->log($content); } } }
這樣就好多了。現在如果要添加其他日志記錄目標,我們可以創建一個新類并將其添加到 Controller 中的 if-else。
但是,我們的控制器仍然負責選擇記錄器。對于控制器,不需要知道不同的記錄器并在它們之間進行選擇。它只需要一個帶有 log() 方法的記錄器類來記錄內容。
使用接口
這種情況就適合使用接口。那么什么是接口?
接口是對對象可以執行的操作的描述。
以我們的示例為例,控制器僅需要帶有 log() 方法的記錄器類。因此,我們的接口必須描述它必須具有 log() 方法。
interface Logger { public function log($content); }
如您所見,它僅包含函數聲明,而不包含其實現,這就是為什么將其稱為抽象的原因。
實現接口時,實現接口的類必須提供接口中定義的抽象方法的實現細節。
在我們的示例中,任何實現 Logger 接口的類都必須提供抽象方法 log () 的實現細節。
然后,我們可以在控制器中注入此接口。
class LogController extends Controller { public function log(Logger $logger) { $logger->log($content); } }
現在,控制器不再關心傳遞給它的記錄器類型。它需要知道的是它必須實現 Logger 接口。
因此,我們需要修改 Logger 類以實現此接口。
class DBLogger implements Logger { public function log() { //將日志記錄到 db } } class FileLogger implements Logger { public function log() { //將日志存儲到 file } } class CloudLogger implements Logger { public function log() { //將日志保存到 cloud } }
現在,我們可以添加更多記錄器,而無需觸及現有代碼。我們要做的就是創建一個實現 Logger 接口的新類。
class RedisLogger implements Logger { public function log() { //將日志存儲到 redis } }
我們的代碼現在看起來就變得靈活,低耦合了,我們可以隨時改變實現方式而不用去改動之前的代碼。
依賴注入
當我們使用的是 Laravel 框架,我們可以使用服務容器去自動注冊接口的實現。
因為 Laravel 提供開箱即用的方法注入,所以我們只需要把接口和實現綁定起來。
首先我們需要創建一個 logger 的配置文件。 就像這樣
<?php return [ 'default' => env('LOG_TARGET', 'file'), 'file' => [ 'class' => App\Log\FileLogger::class, ], 'db' => [ 'class' => App\Log\DBLogger::class, ], 'redis' => [ 'class' => App\Log\RedisLogger::class, ] ];
然后在 app/Providers 路徑下 AppServiceProvider.php 的文件添加如下代碼
class AppServiceProvider extends ServiceProvider { public function register() { $default = config('log.default'); $logger = config("log.{$default}.class"); $this->app->bind( App\Contracts\Logger::class, // the logger interface $logger ); } }
這樣做的效果是,從 logger.php 配置文件讀取默認的 logger ,然后綁定到 Logger interface 。這樣當我們使用 Logger interface ,容器將會幫我們解析并返回默認的 Logger 實例。
因為默認的 logger 是使用 env() 助手指定的,所以我們可以在不同的環境使用不同的 logger ,例如本地環境使用 file ,生產環境使用 db 。
感謝你能夠認真閱讀完這篇文章,希望小編分享的“Laravel面向接口編程的實現”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。