Логика, которую я имел в виду, была следующей:
Фабрика (или абстрактная фабрика в случае слишком большого количества объектов) позаботится о создании самого объекта.
Контейнер сопоставит уникальные идентификаторы с объектами, созданными фабрикой.
И может извлекать объекты на основе этих идентификаторов.
Это простая часть, пользовательская часть должна быть еще проще, вы можете добавить свои собственные методы, чтобы делать любую магию, которая вам нужна, с псевдонимами и тому подобное.
namespace Example;
/**
* Class ObjectFactory
*
* @package Example
*/
class ObjectFactory {
/**
* This is obviosuly not ideal but it can work
* with a limited amount of objects. Otherwise use an
* abstract factory and let each instance take care of a few
* related objects
*
* @param string $objectAlias
*
* @throws \Exception
*/
public function make(string $objectAlias) {
switch($objectAlias) {
case 'object_unique_id_1':
try{
$instance = new $objectAlias;
}catch (\Exception $exception) {
// log or whatever and rethrow
throw new \Exception("Invalid class? maybe, I dunno");
}
// return $instance
// etc
}
}
}
Вы также можете использовать Reflection здесь, чтобы рекурсивно получить аргументы для объекта и вывести новые экземпляры объекта в текущем объекте на основе аргументов в конструкции, по существу, создайте свой собственный маленький контейнер DI.
Но если вы хотите сохранить здравомыслие, используйте что-то вроде Прыщ .
Контейнер:
<?php
namespace Example;
/**
* Class Container
*
* @package Example
*/
class Container {
/**
* @var array
*/
private $map = [];
/**
* @param $objectAlias
* @param $objectInstance
*
* @throws \Exception
*/
public function set($objectAlias, $objectInstance) {
// You can use a try catch here, I chose not to
if(isset($this->map[$objectAlias])) {
throw new \Exception("Already exists");
}
$this->map[$objectAlias] = $objectInstance;
}
/**
* @param $objectAlias
*
* @return bool|mixed
*/
public function get($objectAlias) {
if(isset($this->map[$objectAlias])) {
return $this->map[$objectAlias];
}
return false;
}
}
Специальный контейнер, который будет содержать ваши собственные методы
<?php
namespace Example;
/**
* Class ContainerHashMapThingy
*
* @package Example
*/
class ContainerHashMapThingy extends Container {
// Your methods go here
}
И пример объекта:
<?php
namespace Example;
/**
* Class ExampleObject1
*
* @package Example
*/
class ExampleObject1 {
/**
* @return string
*/
public function alias() {
// This is just for example sake
// You can just as well have a config, another class to map them or not map them at all
return 'example_object_1';
}
}
И реальный пример
<?php
$factory = new \Example\ObjectFactory();
$container = new \Example\Container();
$objectOne = $factory->make('example_object_1');
$container->set('first_object', $objectOne);
Идея в том, чтобы дать вам чистый лист для контейнера + фабрики.
Если вы расширяете контейнер, вы можете реализовывать свои собственные методы, удалять вещи из массива map
и даже переписывать метод set
в соответствии со своими потребностями.
Хотя это не полный ответ, его очень сложно дать, поскольку, как я уже сказал, ваши потребности могут отличаться.
Я очень надеюсь, что это приведет вас на правильный путь.