PHP中的服務容器與依賴註入的思想

来源:https://www.cnblogs.com/heyue0117/archive/2019/11/06/11809057.html
-Advertisement-
Play Games

依賴註入 當A類需要依賴於B類,也就是說需要在A類中實例化B類的對象來使用時候,如果B類中的功能發生改變,也會導致A類中使用B類的地方也要跟著修改,導致A類與B類高耦合。這個時候解決方式是,A類應該去依賴B類的介面,把具體的類的實例化交給外部。 就拿我們業務中常用的通知模塊來說。 1 2 3 4 5 ...


依賴註入

 

當A類需要依賴於B類,也就是說需要在A類中實例化B類的對象來使用時候,如果B類中的功能發生改變,也會導致A類中使用B類的地方也要跟著修改,導致A類與B類高耦合。這個時候解決方式是,A類應該去依賴B類的介面,把具體的類的實例化交給外部。

就拿我們業務中常用的通知模塊來說。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

<?php

/**

 * 定義了一個消息類

 * Class Message

 */

class  Message{

  public function seed()

  {

      return 'seed email';

  }

}

/*

 * 訂單產生的時候 需要發送消息

 */

class Order{

    protected $messager = '';

    function __construct()

    {

        $this->messager = new Message();

    }

    public function seed_msg()

    {

        return $this->messager->seed();

    }

}

$Order = new Order();

$Order->seed_msg();

上面的代碼是我們傳統的寫法。首先由個消息發送的類。然後在我們需要發送消息的地方,調用發送消息的介面。有一天你需要添加一個發送簡訊的介面以滿足不同的需求。那麼你會發現你要再Message類裡面做修改。同樣也要再Order類裡面做修改。這樣就顯得很麻煩。這個時候就有了依賴註入的思路。下麵把代碼做一個調整

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

<?php

/**

 * 為了約束我們先定義一個消息介面

 * Interface Message

 */

interface  Message{

  public function seed();

}

/**

 * 有一個發送郵件的類

 * Class SeedEmail

 */

class SeedEmail implements Message

{

    public function seed()

    {

        return  'seed email';

        // TODO: Implement seed() method.

    }

}

/**

 *新增一個發送簡訊的類

 * Class SeedSMS

 */

class SeedSMS implements Message

{

    public function seed()

    {

        return 'seed sms';

        // TODO: Implement seed() method.

    }

}

/*

 * 訂單產生的時候 需要發送消息

 */

class Order{

    protected $messager = '';

    function __construct(Message $message)

    {

        $this->messager = $message;

    }

    public function seed_msg()

    {

        return $this->messager->seed();

    }

}

//我們需要發送郵件的時候

$message = new SeedEmail();

//將郵件發送對象作為參數傳遞給Order

$Order = new Order($message);

$Order->seed_msg();

//我們需要發送簡訊的時候

$message = new SeedSMS();

$Order = new Order($message);

$Order->seed_msg();

這樣我們就實現了依賴註入的思路,是不是很方便擴展了。

服務容器

我理解的服務容器就是一個自動產生類的工廠。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

<?php

/**

 * 為了約束我們先定義一個消息介面

 * Interface Message

 */

interface  Message{

    public function seed();

}

/**

 * 有一個發送郵件的類

 * Class SeedEmail

 */

class SeedEmail implements Message

{

    public function seed()

    {

        return  'seed email';

        // TODO: Implement seed() method.

    }

}

/**

 *新增一個發送簡訊的類

 * Class SeedSMS

 */

class SeedSMS implements Message

{

    public function seed()

    {

        return 'seed sms';

        // TODO: Implement seed() method.

    }

}

/**

 * 這是一個簡單的服務容器

 * Class Container

 */

class Container

{

    protected $binds;

    protected $instances;

    public function bind($abstract, $concrete)

    {

        if ($concrete instanceof Closure) {

            $this->binds[$abstract] = $concrete;

        } else {

            $this->instances[$abstract] = $concrete;

        }

    }

    public function make($abstract, $parameters = [])

    {

        if (isset($this->instances[$abstract])) {

            return $this->instances[$abstract];

        }

        array_unshift($parameters, $this);

        return call_user_func_array($this->binds[$abstract], $parameters);

    }

}

//創建一個消息工廠

$message = new  Container();

//將發送簡訊註冊綁定到工廠裡面

$message->bind('SMS',function (){

     return   new  SeedSMS();

});

//將發送郵件註冊綁定到工廠

$message->bind('EMAIL',function (){

   return new  SeedEmail();

});

//需要發送簡訊的時候

$SMS  = $message->make('SMS');

$SMS->seed();

container是一個簡單的服務容器裡面有bind,make兩個方法

bind是向容器中綁定服務對象。make則是從容器中取出對象。

bind

在bind方法中需要傳入一個 concrete 我們可以傳入一個實例對象或者是一個閉包函數。

可以看到我這全使用的是閉包函數,其實也可以這樣寫

1

2

$sms = new  SeedSMS();

$message->bind('SMS',$sms);

後面這種寫法與閉包相比的區別就是我們需要先實例化對象才能往容易中綁定服務。而閉包則是我們使用這個服務的時候才去實例化對象。可以看出閉包是有很多的優勢的。

make

make方法就從容器中出去方法。裡面首先判斷了instances變數中是否有當前以及存在的服務對象,如果有直接返回。如果沒有那麼會通過 call_user_func_array返回一個對象.

擁有一個明確的學習思路能更高效化的學習

 

點此加入該群學習


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 最近兩個月一直在研究 Swoole,那麼藉助這篇文章,我希望能夠把 Swoole 安利給更多人。雖然 Swoole 可能目前定位是一些高級 phper 的玩具,讓中低級望而生畏,可能對一些應用場景也一臉懵逼,但其實沒這麼難的。 在 Swoole 官網的自我介紹是“面向生產環境的 PHP 非同步網路通信 ...
  • 這篇文章僅僅只實現一個 Redis 連接池,篇幅就太少了,順便將前幾篇整合一下。Demo 中大概包含這些點: 實現 MySQL 連接池 實現 MySQL CURD 方法的定義 實現 Redis 連接池 實現 Redis 方法的定義 滿足 HTTP、TCP、WebSocket 調用 提供 Demo 供 ...
  • 下載ProcessExplorer ProcessExplorer下載地址:ProcessExplorer 下載運行代碼 打開ProcessExplorer 查看javaw.exe的pid jstack pid號 > G:\1.log(保存路徑) 查看tid javaw.exe右鍵屬性-》點Thre ...
  • 這篇文章給大家分享的內容是關於Swoft 源碼剖析之Swoole和Swoft的一些介紹(Task投遞/定時任務篇),有一定的參考價值,有需要的朋友可以參考一下。 前言 Swoft的任務功能基於Swoole的Task機制,或者說Swoft的Task機制本質就是對Swoole的Task機制的封裝和加強。 ...
  • 最近,決定在一個項目用tp5進行APP介面開發,用Python做數據分析,然後這就面臨一個問題:PHP和Python如何進行數據交互? 思路 我解決此問題的方法是利用了PHP的passthru函數來調用命令運行Python腳本。 實現 在PHP中調用命令運行Python腳本 1 2 3 4 5 6 ...
  • 在實際開發中,有時候為了及時處理請求和進行響應,我們可能會多任務同時執行,或者先處理主任務,也就是非同步調用,非同步調用的實現有很多,例如多線程、定時任務、消息隊列等, 這一章節,我們就來講講@Async非同步方法調用。 一、@Async使用演示 @Async是Spring內置註解,用來處理非同步任務,在S ...
  • 如何提高效率問題,往往同樣的功能,不一樣的代碼,出來的效率往往大不一樣。 ● 用單引號代替雙引號來包含字元串,這樣做會更快一些。因為PHP會在雙引號包圍的字元串中搜尋變數,單引號則不會,註意:只有echo能這麼做,它 是一種可以把多個字元串當作參數的“函數”(譯註:PHP手冊中說echo是語言結構, ...
  • php數組中有一些函數與數學相關的函數,大多都是以array開頭然後下劃線接一個數學上的英文單詞,如下: 1 array_diff() 2 array_diff_assoc() 3 array_intersect() 4 array_intersect_assoc() 5 array_sum() 6 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...