Я не знаю много о конкретной библиотеке, но при условии, что она позволяет вам использовать фабрику, пусть фабрика возвращает тот же экземпляр.
Редактировать: Хорошо, это просто на странице индекса 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 делают.Если нет, то это действительно легко реализовать с помощью Decorator.Представьте себе что-то вроде этого:
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
*/
}