通过Builder进行的DI是否等同于服务定位器的反模式?

时间:2018-11-05 15:19:12

标签: oop dependency-injection ioc-container builder service-locator

我有一个由构建器创建的Foo类的对象。生成器将自身传递给A的构造函数,然后从中构造A的所有属性。

  • Foo需要另一个对象(Bar)作为依赖项。

  • Builder将该对象作为其构造函数的参数接收 实例化。

  • BuildDirector接收Builder作为其构造函数的自变量 实例化。

  • 客户端将BuildDirector作为其构造函数的自变量接收 实例化。

此依赖项注入链由应用启动时的Pimple DI容器处理:

$dependencies = new \Pimple\Container();

$dependencies['FooDependency'] = functiom($c) {
    return new \App\Bar();
};
$dependencies['FooBuilder'] = function($c) {
    return new \App\FooBuilder($c['FooDependency']);
};
$dependencies['FooBuildDirector'] = function($c) {
    return new \App\FooBuildDirector($c['FooBuilder']);
};

$dependencies['Client'] = function($c) {
    return new \App\Client($c['FooBuildDirector']);
};

$client = $dependencies['Client'];
  • 当需要Foo时,客户端调用已传递给它的FooBuildDirector来构建对象。
  • 然后,
  • FooBuildDirector在FooBuilder中设置所有对象属性,并调用其“ build()”方法。
  • 然后,
  • FooBuilder创建一个新的Foo并将其自身传递给其构造函数。
  • Foo从FooBuilder设置其所有属性以及依赖项。

FooBuildDirector:

class FooBuildDirector
{

    protected $fooBuilder;

    public function __construct(FooBuilderInterface $fooBuilder)
    {
        $this->fooBuilder = $fooBuilder;
    }

    public function build(): FooInterface
    {
        return $this->fooBuilder->reset()
                                ->setFooProperty1('something')
                                // set some more properties...
                                ->build();
    }

}

FooBuilder:

class FooBuilder implements FooBuilderInterface
{

    protected $fooProperty1;
    // some more Foo properties
    protected $fooDependency;

    public function __construct(FooDependencyInterface $fooDependency)
    {
        $this->fooDependency = $fooDependency;
    }

    public function reset(): FooBuilderInterface
    {
        // set all Foo properties to null
    }

    public function build(): FooInterface
    {
        return new Foo($this);
    }


    // some setters and getters for Foo properties

 }

Foo:

class Foo implements FooInterface
{

    protected $property1;
    // some other properties
    protected $dependency;

    public function __construct(FooBuilderInterface $builder)
    {
        $this->setDependency($builder->getFooDependency())
             ->setProperty1($builder->getFooProperty1())
             // set some other properties;
    }

    // some other methods

}

我不确定将依赖项传递到Builder内部的Foo对象是否与使用Service Locator反模式不同,因为它隐藏了依赖关系,并使得从查看Foo的构造函数参数类型中看不出来。 >

考虑到必须使用Builder,是否有更好的方法(因为在Foo的实例化中还有很多其他属性需要设置)?也许需要将构造器和依赖项都作为Foo的构造器参数?

0 个答案:

没有答案