У меня есть «фабрика провайдеров», которая создает реализацию конкретного провайдера. Для создания правильной реализации необходимо, помимо других параметров, TypeID.
Проблема в том, чтобы пройти правильно TypeID на заводе, мне нужно проверить и, при необходимости, изменить его.
И для этого, помимо других параметров, мне нужен экземпляр конкретного провайдера. Вот в чем проблема — провайдер должен быть одноэлементным (я действительно не хочу делать его одноэлементным с большой буквы S), потому что он запрашивает базу данных и кэширует результат во внутреннем свойстве.
Поэтому мой вопрос — есть ли более подходящий шаблон для использования или другой способ достижения чего-то подобного?
class ProviderFactory
{
public function createProvider($typeId)
{
if ($typeId == 2) {
return new Provider2($arg1, $arg5);
} elseif ($typeId == 4) {
return new Provider4();
} else {
return new ProviderDefault($typeId, $arg1, $arg2, $arg3, $arg4);
}
}
}
interface ProviderInterface
{
public function getCost();
}
class ProviderDefault implements ProviderInterface
{
public function __construct($arg1, $arg2, $arg3, $arg4) {}
public function getCost() { /*implementation*/ }
}
class Provider2 implements ProviderInterface
{
public function __construct($arg1, $arg5) {}
public function getCost() { /*implementation*/ }
}
// this call can be implemented with the following condition
// if ($typeId == 2) {
// if ($provider2->getCost() !== null)
// $typeId = 1;
// }
//
$typeId = fixAndValidateTypeId($typeId, new Provider2($arg1, $arg5));
$factory = new ProviderFactory();
$provider = $factory->createProvider($typeId);
Я предлагаю вам реализовать шаблон ChainOfResponsibility в ProviderFactory, чтобы вам не нужно было изменять ProviderFactory каждый раз, когда добавляется новый поставщик или изменяется логика. Вам просто нужно добавить метод RegisterProvider (провайдер IProvider), чтобы добавить провайдеров в цепочку, а затем просто циклически проходить по этой цепочке провайдеров, вызывая bool: DoesProviderSuit (int typeId, out IProvider) каждого IProvider.
Надеюсь, вы поймаете идею, удачи!
Других решений пока нет …