控制反轉 依賴注入理解
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核心有興趣的可以去看一下,也是自己做個記錄。