Я пытаюсь создать набор фабричных классов для нашей системы, где некоторые объекты, созданные фабрикой, также должны быть инициализированы, прежде чем они могут быть использованы должным образом.
Пример:
$foobar = new Foobar();
$foobar->init( $qux, ... );
// $foobar ready for usage
Для того же примера, допустим, что объект $qux
является единственной зависимостью, в которой нуждается Foobar
.Я хотел бы получить следующее:
$foobar = Foo_Factory( 'bar' );
Чтобы избежать необходимости передавать объект $qux
по всей системе и передавать его классу фабрики в качестве другого параметра, яЯ хотел бы выполнить инициализацию Foobar
непосредственно в фабричном классе:
class Foo_Factory {
public static function getFoo( $type ) {
// some processing here
$foo_name = 'Foo' . $type;
$foo = new $foo_name();
$foo->init( $qux );
return $foo;
}
}
Есть несколько решений, которые приходят на ум, но ни одно из них не является идеальным:
- Добавитьметод статического установщика для
$qux
фабричного класса, и пусть он хранит ссылку на $qux
в закрытой статической переменной.Система может установить $qux
в начале, а фабричный класс может предотвратить любые будущие изменения (по соображениям безопасности).Хотя этот подход работает, использование статического параметра для хранения ссылки на $qux
проблематично во время модульного тестирования (например, он успешно выживает между отдельными тестами благодаря своему статическому состоянию). - Создание нового класса контекста с помощью Singletonшаблон и пусть фабричный класс использует его, чтобы получить ссылку на
$qux
.Это может быть немного более чистым способом сделать это, чем вариант № 1 (хотя мы переносим статическую проблему из класса фабрики в класс контекста). - Полное использование внедрения зависимостей, то есть передача
$qux
влюбой объект, который использует класс фабрики, и пусть этот объект передает его классу фабрики в качестве другого параметра: Foo_Factory::getFoo($type, $qux);
. - То же, что и выше (# 3), но вместо передачи
$qux
вдольсистема, вместо этого передайте экземпляр класса фабрики (т. е. в этом случае он будет не статичным, а инстанцируемым).
Что бы вы порекомендовали, пожалуйста?Любая из четырех альтернатив, упомянутых выше, или есть лучший способ сделать это, пожалуйста?
Примечание: я не хочу входить в static is evil
флейм здесь, просто пытаюсь придумать лучшеерешение.