如何使用PHP实现工厂类 - 依赖注入

时间:2013-12-09 13:20:28

标签: php dependency-injection factory

将以下代码作为我想要的示例:

class SomethingController extends Factory    
{
    private $somethingRepository;

    public function __Construct( ISomethingRepository $repo )
    {
        $this->somethingRepository = $repo;
    }
}

class Factory
{        
    public function __Construct()
    {
        // The following call to AddBinding would push into SomethingController the new instance of the class denoted in my AddBinding second parameter.
        $this->AddBinding( ISomethingRepository, MySQLSomethingRepository);
        // So in this case, if the controller i'm extending has a construct parameter of ISomethingRepository, then make the parameter equal a new MySQLSomethingRepository()
        // Then if I want to use JSONSomethingRepository in the future, I only have to change the one AddBinding call and the controller will still work.
    }

    public function AddBinding( $interface, $concrete )
    {
        // Somehow assign the constructor properties of the extending class as new instances of the bindings i have called upon in the construct of my factory class (see this class's construct)
        // Pseudo code:
        // ----------------------
        $calledClass = get_called_class();
        $class = new \ReflectionClass( $calledClass );

        $method = $class->getMethod( "__construct" );

        $params = $method->getParameters();

        foreach( $params as $param )
        {
            if ( $param == $interface )
            {
                return new $concrete;
            }
        }
        // /Pseudo code:
        // ----------------------
    }
}  

我想实现一种工厂类。

  • 此工厂类将由控制器类扩展。
  • 工厂类将查看控制器类的构造参数,并根据工厂中的AddBindings方法创建对象的新实例。

假设我想拥有一个MySQLSomethingRepository,其中包含来自MySQL的数据...注入我的SomethingController ...某处我需要声明

SomethingController( new MySQLSomethingRepository() )... 

希望我的工厂班级能够处理......

我正在做的当前方式是强制与数据源直接耦合......这使得用以下方法进行测试的情况非常困难:

private $somethingRepository = new MySQLSomethingRepository();

所以想象一下,如果我在其他控制器的负载中使用了相同的存储库,并且我想将我的数据库源更改为某些json数据,并且我实现了以下存储库“JsonSomethingRepository”,我必须将所有控制器更改为:

private $somethingRepository = new JsonSomethingRepository();

我如何实现我的Factory类,以便它可以处理在AddBindings函数中创建我的控制器类要求的实例?

1 个答案:

答案 0 :(得分:0)

在Adapter模型中设计一个抽象类,并为子类提供一些常用方法。 您可以使用适配器设计两个repos,以便在控制器中注入。

我的建议是使用Abstract类并按以下方式执行:

class SomethingController extends AbstractController {
}

abstract class AbstractController {
    protected $somethingRepository;
    public function __Construct(ISomethingRepository $repo) {
        $this->somethingRepository = $repo;
        $this->AddBinding ( ISomethingRepository, MySQLSomethingRepository );
    }
    public function AddBinding($interface, $concrete) {
        // Somehow assign the constructor properties of the extending class as new instances of the bindings i have called upon in the construct of my factory class (see this class's construct)
    }
}

希望这会有所帮助。