lundi 25 mai 2015

Remove "factory"<->"concrete implementation" dependency

I have a "provider factory" which creates an implementation of a concrete provider. To create correct implementation it needs, among other parameters, typeId. The problem is that in order to pass the correct typeId to the factory, I need to validate and, if necessary, change it. And in order to do that, among other parameters, I need an instance of a particular provider. Which is where the problem is - the provider should be singleton (I really don't want to make it a Singleton with a capital S), because it queries a database and caches the result in the internal property.

So my question is - is there a more suitable pattern to use or another way to achieve something similar?

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);

Aucun commentaire:

Enregistrer un commentaire