學習記錄-Laravel 核心 依賴注入 控制反轉 反射

draven發表於2019-08-08

控制反轉 依賴注入理解

interface DbConnect {

    public function connect();
}

class DbA implements DbConnect {

    public function connect()
    {
        // TODO: Implement test_echo() method.
        echo 'A';
    }
}
class DbB implements DbConnect {

    public function connect()
    {
        // TODO: Implement test_echo() method.
        echo "B";
    }
}

class ConnectDb {

    protected $connects;

    public function __construct()
    {
        $this->connect = new DbA();
    }

    public function connect()
    {
        echo $this->connect->connect();
    }
}

上面寫法可以實現資料庫連線功能,但是要切換到B資料庫就要修改ConnectDb類,這樣程式碼沒法達到低耦合,也不符合程式設計開放封閉原則。我們可以把連線的類用函式傳參的方式傳進ConnectDb建構函式裡.

class ConnectDb {

    protected $connects;

    public function __construct(DbConnect $dbConnect)
    {
        $this->connect = $dbConnect;
    }

    public function connect()
    {
        echo $this->connect->connect();
    }
}

$ConnectDb = new ConnectDb(new DbA());
$ConnectDb->connect();

這樣我們就可以不修改ConnectDb而是用建構函式引數傳遞的方式切換資料庫,這就是控制反轉(感覺好像工廠模式。。。),不需要自己內容修改,通過外部傳遞引數,這種由外部負責其依賴需求的行為,稱控制反轉(IoC)

不通過自己內部new 物件或者例項,而是通過函式或者建構函式傳遞進來。稱為依賴注入(DI)

反射

剛畢業那會面試一家公司面試就問我了不瞭解反射,當時給我問的一懵。工作這麼長時間了其實還是不瞭解。。。。

反射其實就是根據類名返回這個類的任何資訊,比如該類的方法,引數,屬性等等

ReflectionClass 類報告了一個類的有關資訊。

//   — 初始化 ReflectionClass 類
$reflectionClass = new ReflectionClass('ConnectDb');

//   — 獲取類的建構函式   一個 ReflectionMethod 物件,反射了類的建構函式,或者當類不存在建構函式時返回 NULL。
$constructor     = $reflectionClass->getConstructor();

//   - 獲取建構函式所有依賴引數
$dependencies    = $constructor->getParameters();

//   - 建立類的新的例項。給出的引數將會傳遞到類的建構函式。
$ConnectDb       = $reflectionClass->newInstance();

//   - 建立一個類的新例項,給出的引數將傳遞到類的建構函式。這個引數以 array 形式傳遞到類的建構函式 返回值 返回類的例項
$ConnectDb       = $reflectionClass->newInstanceArgs($dependencies);

我們可以建立一個方法,利用反射的機制拿到ConnectDb類的建構函式,然後拿到建構函式的引數物件,用遞迴的方法建立引數依賴,最後呼叫newInstanceArgs方法生成ConnectDb例項

interface DbConnect {

    public function connect();
}

class DbA implements DbConnect {

    public function connect()
    {
        // TODO: Implement test_echo() method.
        echo 'A';
    }
}
class DbB implements DbConnect {

    public function connect()
    {
        // TODO: Implement test_echo() method.
        echo "B";
    }
}

class ConnectDb {

    protected $connects;
    //反射是不能動態建立介面的
    public function __construct(DbA $dbConnect)
    {
        $this->connect = $dbConnect;
    }

    public function connect()
    {
        echo $this->connect->connect();
    }
}

function make ($concrete) {
    //   — 初始化 ReflectionClass 類
    $reflectionClass = new ReflectionClass($concrete);
    //   — 獲取類的建構函式   一個 ReflectionMethod 物件,反射了類的建構函式,或者當類不存在建構函式時返回 NULL。
    $constructor     = $reflectionClass->getConstructor();

    //如果不需要傳遞引數直接返回例項
    if (is_null($constructor)) {
        return $reflectionClass->newInstance();
    } else {
    //   - 獲取建構函式所有依賴引數
        $dependencies    = $constructor->getParameters();
        $instance = getdependencies($dependencies);
        return $reflectionClass->newInstanceArgs($instance);
    }

}

function getdependencies($parameter)
{
    $dependencies = [];
    foreach ($parameter as $paramete) {
        //返回物件例項 object 所屬類的名字。返回物件例項 object 所屬類的名字。 如果 object 不是一個物件則返回 FALSE。
        $dependencies[] = make($paramete->getClass()->name);
    }
    return $dependencies;
}

$ConnectDb = make('ConnectDb');
$ConnectDb->connect();

總結:

  • 控制反轉(IoC):不修改類內部自身,通過外部引數傳遞的方式,由外部負責其依賴需求的行為。
  • 依賴注入(DI) :不通過自己new 或例項例項化,通過函式或者建構函式傳遞進來。
  • 反射:根據類名獲取類的資訊,方法、屬性、引數等等

文章借鑑,也不算借鑑了。抄了深入laravel核心有興趣的可以去看一下,也是自己做個記錄。

與其感慨路難行,不如馬上出發

相關文章