### 簡介:
服務定位器是框架流行一種設計模式,它和依賴注入一樣都是控制反轉(IOC)的實現,目的在于解耦組件和應用之間的依賴;舉個簡單例子,我們有個日志組件,系統所有應用程序都
會用到這個日志組件,每次使用我們需要通過new實例化對象,這樣的問題是導致整個系統都是new Logger()實例化代碼,萬一某天組件的名稱改了,那所有實例化都要跟著改變;
### 思路:
相對于依賴注入,服務定位器的實現其實很簡單,用一個容器注冊組件,應用程序用過key獲取組件實例
### 簡單的代碼:
```php
// 這是一個服務定位器
class ServiceLocator {
public function get() {}
public function set() {}
}
// 注冊組件
$locator = new ServiceLocator();
$locator->set('logger', new Logger());
// 使用組件
$logger = $locator->get('loggger');
$logger->write();
```
### zcswoole服務定位器使用
> 借鑒于Yii的設計模式,zcswoole實例化App類之后,將App實例賦值給了ZCSwoole::$app,在整個系統中可以通過ZCSwoole::$app來訪問定位服務器
服務器
- 首先會讀取配置文件中用戶自定義組件配置信息
```php
return [
'components' => [
'logger' => [
'class' => 'zcswoole\Logger',
],
]
]
```
- 合并系統組件,用戶可以覆蓋系統組件配置,只要class指向自己自定義的類即可
```php
/**
* 核心組件
* @return array
*/
public function coreComponents():array
{
return [
'logger' => [
'class' => 'zcswoole\components\Logger'
],
'session' => [
'class' => 'zcswoole\components\Session'
]
];
}
```
- 注冊組件
```php
/**
* 注冊組件到容器
*/
public function injectComponents():void
{
foreach ($this->allComponents() as $name => $properties) {
$class = $properties['class'];
ZCSwoole::$con->set($name, ['class' => $class], $properties);
}
}
```
- 組件是在swoole_server啟動start之前注冊到容器的,這意味著這些組件常駐在內存中,所以涉及到狀態類的或數據庫連接的要注意了,這是全局周期的,狀態類改變結果會
作用到另一個調用者,不要在start之前實例化數據庫,這是因為在多進程不能共享一個數據庫連接,否則數據會錯亂