註冊器模式(Registry Pattern)提供全域存取點,管理共享物件實例,是依賴注入容器的簡化形態。本文展示基於 ArrayObject 的線程安全實現。
class Registry extends ArrayObject {
private static $_instance = null;
// 單例模式
public static function getInstance() {
if (self::$_instance === null) {
self::$_instance = new self();
}
return self::$_instance;
}
// 靜態代理方法
public static function set($name, $value) {
self::getInstance()->offsetSet($name, $value);
}
public static function get($name) {
$ins = self::getInstance();
return $ins->offsetExists($name) ? $ins->offsetGet($name) : null;
}
public static function has($name) {
return self::getInstance()->offsetExists($name);
}
public static function remove($name) {
self::getInstance()->offsetUnset($name);
}
}
// 註冊服務物件
$db = new PDO('mysql:host=localhost;dbname=test', 'root', '');
Registry::set('db', $db);
$cache = new Redis();
$cache->connect('127.0.0.1', 6379);
Registry::set('cache', $cache);
// 任意處獲取
$db = Registry::get('db');
$stmt = $db->query('SELECT * FROM users');
$user = $stmt->fetch();
// 檢查是否註冊
if (Registry::has('logger')) {
Registry::get('logger')->info('Request processed');
}
Closure 實現惰性實例化service.db、config.app 格式ContainerInterface 標準化| 優點 | 缺點 |
|---|---|
| 全域存取便利 | 隱式依賴難追蹤 |
| 單例保證資源復用 | 單元測試需 Mock 容器 |
| 實現簡單輕量 | 非嚴格 DI 容器替代品 |
最佳實踐:僅用於基礎設施服務(DB、Cache、Config、Logger),業務邏輯物件優先採用建構子注入。現代框架(Laravel、Symfony)已內建完整 DI 容器,舊專案遷移時可漸進式替換。