1. 程式人生 > >依賴注入模式(Dependency Injection)

依賴注入模式(Dependency Injection)

1、模式定義

依賴注入(Dependency Injection)是控制反轉(Inversion of Control)的一種實現方式。

我們先來看看什麼是控制反轉。

當呼叫者需要被呼叫者的協助時,在傳統的程式設計過程中,通常由呼叫者來建立被呼叫者的例項,但在這裡,建立被呼叫者的工作不再由呼叫者來完成,而是將被呼叫者的建立移到呼叫者的外部,從而反轉被呼叫者的建立,消除了呼叫者對被呼叫者建立的控制,因此稱為控制反轉。

要實現控制反轉,通常的解決方案是將建立被呼叫者例項的工作交由 IoC 容器來完成,然後在呼叫者中注入被呼叫者(通過構造器/方法注入實現),這樣我們就實現了呼叫者與被呼叫者的解耦,該過程被稱為依賴注入。

依賴注入不是目的,它是一系列工具和手段,最終的目的是幫助我們開發出鬆散耦合(loose coupled)、可維護、可測試的程式碼和程式。這條原則的做法是大家熟知的面向介面,或者說是面向抽象程式設計。

2、UML 類圖

Dependency-Injection-UML

3、示例程式碼

在本例中,我們在 Connection 類(呼叫者)的構造方法中依賴注入 Parameters 介面的實現類(被呼叫者),如果不使用依賴注入的話,則必須在 Connection 中建立該介面的實現類例項,這就形成緊耦合程式碼,如果我們要切換成該介面的其它實現類則必須要修改程式碼,這對到測試和擴充套件而言都是極為不利的。

AbstractConfig.php

12345678910111213141516171819 <?phpnamespaceDesignPatterns\Structural\DependencyInjection;/** * AbstractConfig類 */abstractclassAbstractConfig{/**     * @var Storage of data     */protected$storage;publicfunction__construct($storage){$this->storage=$storage
;}}

Parameters.php

1234567891011121314151617181920212223242526 <?phpnamespaceDesignPatterns\Structural\DependencyInjection;/** * Parameters介面 */interfaceParameters{/**     * 獲取引數     *     * @param string|int $key     *     * @return mixed     */publicfunctionget($key);/**     * 設定引數     *     * @param string|int $key     * @param mixed      $value     */publicfunctionset($key,$value);}

ArrayConfig.php

12345678910111213141516171819202122232425262728293031323334353637 <?phpnamespaceDesignPatterns\Structural\DependencyInjection;/** * ArrayConfig類 * * 使用陣列作為資料來源 */classArrayConfigextendsAbstractConfigimplementsParameters{/**     * 獲取引數     *     * @param string|int $key     * @param null $default     * @return mixed     */publicfunctionget($key,$default=null){if(isset($this->storage[$key])){return$this->storage[$key];}return$default;}/**     * 設定引數     *     * @param string|int $key     * @param mixed $value     */publicfunctionset($key,$value){$this->storage[$key]=$value;}}

Connection.php

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849 <?phpnamespaceDesignPatterns\Structural\DependencyInjection;/** * Connection類 */classConnection{/**     * @var Configuration     */protected$configuration;/**     * @var Currently connected host     */protected$host;/**     * @param Parameters $config     */publicfunction__construct(Parameters$config){$this->configuration=$config;}/**     * connection using the injected config     */publicfunctionconnect(){$host=$this->configuration->get('host');// connection to host, authentication etc...//if connected$this->host=$host;}/*     * 獲取當前連線的主機     *     * @return string     */publicfunctiongetHost(){return$this->host;}}

4、測試程式碼

Tests/DependencyInjectionTest.php

12345678910111213141516171819202122232425 <?phpnamespaceDesignPatterns\Structural\DependencyInjection\Tests;useDesignPatterns\Structural\DependencyInjection\ArrayConfig;useDesignPatterns\Structural\DependencyInjection\Connection;classDependencyInjectionTestextends\PHPUnit_Framework_TestCase{protected$config;protected$source;publicfunctionsetUp(){$this->source=include'config.php';$this->config=newArrayConfig($this->source);}publicfunctiontestDependencyInjection(){$connection=newConnection($this->config);$connection->connect();$this->assertEquals($this->source['host'],$connection->getHost());}}

Tests/config.php

123 <?phpreturnarray('host'=>'github.com');

5、總結

依賴注入模式需要在呼叫者外部完成容器建立以及容器中介面與實現類的執行時繫結工作,在 Laravel 中該容器就是服務容器,而介面與實現類的執行時繫結則在服務提供者中完成。此外,除了在呼叫者的建構函式中進行依賴注入外,還可以通過在呼叫者的方法中進行依賴注入。

參考資料: