我对具体的库了解不多,但假设它允许您使用工厂,让工厂返回相同的实例。
编辑:好的,这只是在 Bucket GitHub 索引页面上。
class MyFactory {
function new_PDO($container) {
return new PDO("mysql:host=localhost;dbname=addressbook", "root", "secret");
}
}
$bucket = new bucket_Container(new MyFactory());
$db = $bucket->get('pdo');
因此,就您而言,您可以简单地执行以下操作:
class MyFactory {
private $pdo;
function new_Database($container) {
if($this->pdo){
return $this->pdo;
}
return $this->pdo = new PDO("mysql:host=localhost;dbname=addressbook", "root", "secret");
}
}
$factory = new MyFactory();
$session_container = new bucket_Container($factory);
$session_container->create('Database_Sessions');
$log_container = new bucket_Container($factory);
$log_container->create('Database_Log');
类似的事情。看起来不像火箭科学。
Edit2:我没有足够的代表点来评论这个问题(有点傻),但为了回应您的“模块化”问题:将容器视为应用程序的“粘合剂”。事实上,如果您有一个大型应用程序,您可能只想“粘合”在应用程序的隔离部分内。这是一个有效的封装问题。但即便如此,您仍然需要一个在最高抽象级别处理注入的容器。如果您只是为应用程序的每个部分创建一个单独的容器,那么您要么会得到不必要的实例重复,要么必须应用另一级别的实例管理,这不会以任何方式改进封装:您仍然在应用程序的不同部分之间共享实例。
我的建议是在引导级别使用单个容器。如果您想为应用程序的特定部分(模块、插件等)添加封装,请使用“子容器”。子容器从父容器继承实例,但父容器对子容器一无所知(就他而言,他仍然是一个单身汉;))。可能是 Bucket 默认支持这个,我知道其他 DI 容器也支持。如果没有,使用装饰器实现起来真的很容易。想象一下这样的事情:
class MyContainerType extends bucket_Container {
private $_parent;
private $_subject;
public function __construct($factory = null, bucket_Container $parent = null){
$this->_parent = $parent;
$this->_subject = new bucket_Container($factory);
}
public function get($key){
$value = $this->_subject->get($key);
if($value){
return $value;
}
return $this->_parent->get($key);
}
/**
* Override and delegation of all other methods
*/
}