PHP 控制反轉(IOC)和依賴注入(DI)

柳旦旦發表於2021-01-19

對於“控制反轉(IOC)”和“依賴注入(DI)”兩個概念,首先要明白以下概念:

  • 控制反轉(IOC)是一種思想,依賴注入(DI)是實施這種思想的方法;
  • IOC 意味著將你設計好的物件交給容器控制,而不是傳統的在物件內部控制;
  • 依賴注入(DI)實現了控制反轉(IOC);

一:介面注入

<?php

/**
 * 定義一個訊息介面
 * Interface Message
 */
interface Message
{
    public function send();
}

/**
 * 傳送郵件的訊息類
 * Class SendEmail
 */
class SendEmail implements Message
{

    public function send()
    {
        echo "email 傳送成功!";
    }
}

/**
 * 傳送簡訊的訊息類
 * Class SendSms
 */
class SendSms implements Message
{

    public function send()
    {
        echo "sms 傳送成功!";
    }
}

/**
 * 模擬購買流程
 * Class Order
 */
class Order
{
    //TODO::下單
    //TODO::購買
    //傳送訊息

    /**
     * @var String 訊息內容
     */
    protected String $message;

    function __construct(Message $message)
    {
        $this->message = $message;
    }

    public function send_msg()
    {
        return $this->message->send();
    }
}

//TODO::比如購買成功了,這裡開始傳送訊息
$message = new SendEmail();//傳送郵件
//$message = new SendEmail();//傳送簡訊
$order = new Order($message);
$order->send_msg();

分析

Order 類依賴訊息類的 Message 介面

$order = new Order($message);

具體的訊息類例項化交給外部處理,不論你是傳送簡訊還是郵件,你自己例項化就好,不要影響我的 Order 類,你只需要把 Message 的介面實現類給我就好

$message = new SendEmail();//傳送郵件
//$message = new SendEmail();//傳送簡訊
$order = new Order($message); 
$order->send_msg();

二:構造器注入

<?php

/**
 * 構造器注入
 * 定義一個有建構函式的類
 * Class IocB
 */
class iocAA
{
    public $b;

    public $c;

    public function __construct($iocB, $iocC)
    {
        $this->b = $iocB;
        $this->c = $iocC;
    }

    public function Method()
    {
        $this->b->Method();
        $this->c->Method();
    }
}

class IocB
{

    public function Method()
    {
        echo '我是 IocB 的 Method 方法';
    }
}

class IocC
{
    public function Method()
    {
        echo '我是 IocC 的 Method 方法';
    }
}
$a = new iocAA(new IocB(), new IocC());
$a->Method();

分析

進行例項化類的時候,對建構函式的兩個引數進行例項化賦值(將例項化後的物件賦值給 iocAA 類 的兩個屬性)

$a = new iocAA(new IocB(), new IocC());

然後呼叫物件的方法即可

$a->Method();

三:setter 方法注入

<?php

class IocC
{
    private $db;

    private $file;

    function setDb($db)
    {
        $this->db = $db;
    }

    function setFile($file)
    {
        $this->file = $file;
    }
}

class file
{
    public function __construct()
    {
        echo "file 的 建構函式執行了" . "\n";
    }

    public function run()
    {
        echo "file 的 run" . "\n";
    }
}

class db
{
    public function __construct()
    {
        echo "db 的 建構函式執行了" . "\n";
    }

    public function run()
    {
        echo "db 的 run" . "\n";
    }
}

$iocC = new IocC();
$iocC->setdb(new db());
$iocC->setfile(new file());

分析

先例項化 IocC 類

$iocC = new IocC();

接著呼叫 IocC 類的方法使用,呼叫 IocC 的方法 setDb 和 setFile 的時候,需要把例項化的物件當做引數傳進去

$iocC->setdb(new db());
$iocC->setfile(new file());
本作品採用《CC 協議》,轉載必須註明作者和本文連結
✍️部落格文章皆為網路收藏整理,作書籤使用,方便後期查閱。

相關文章