依賴注入
當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回傳一個物件.

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

點此加入該群學習
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/121040.html
標籤:PHP
上一篇:線性表
下一篇:php陣列的數學功能相關常用函式