具有对象初始化的工厂类 - 试图避免静态

Mic*_*icE 7 php static factory-pattern

我正在尝试为我们的系统设计一组工厂类,其中工厂创建的一些对象也需要在正确使用之前进行初始化.

例:

$foobar = new Foobar();
$foobar->init( $qux, ... );
// $foobar ready for usage
Run Code Online (Sandbox Code Playgroud)

对于相同的示例,假设该$qux对象是唯一Foobar需要的依赖项.我想要的是:

$foobar = Foo_Factory( 'bar' );
Run Code Online (Sandbox Code Playgroud)

为了避免需要$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;
    }

}
Run Code Online (Sandbox Code Playgroud)

想到的解决方案很少,但没有一个是理想的:

  1. 将静态setter方法添加$qux到工厂类,并让它将引用存储$qux在私有静态变量中.系统可以$qux在开始时设置,工厂类可以防止将来的任何更改(出于安全原因).
    虽然这种方法有效,但是$qux在单元测试期间使用静态参数来存储引用是有问题的(例如,由于其静态状态,它很快就能在各个测试之间存活).
  2. 使用Singleton模式创建一个新的上下文类,并让工厂类使用它来获取对它的引用$qux.这可能比选项#1更简洁一些(尽管我们将静态问题从工厂类移到上下文类).
  3. 一直使用依赖注入,即传递$qux给使用工厂类的任何对象,并让该对象将其作为另一个参数传递给工厂类:Foo_Factory::getFoo($type, $qux);.
  4. 与上面(#3)相同,但不是传递$qux系统,而是传递工厂类的实例(即在这种情况下,它不是静态的,而是可实例化的).

你会推荐什么?上面提到的四种替代品中的任何一种,还是有更好的方法来做到这一点?

注意:我不想在static is evil这里遇到一个火焰,只是想找到最好的解决方案.

San*_*hal 5

我会一直使用依赖注入.但是,不要在任何地方传递$ qux,只需在Dependency Injector Container中注册它,然后让容器对其进行排序.在Symfony Component中说:

// Create DI container
$container = new sfServiceContainerBuilder();

// Register Qux
$container->setService('qux', $qux);
// Or, to have the DI instanciate it
// $container->register('qux', 'QuxClass');

// Register Foobar
$container->register('foobar', 'Foobar')
          ->addArgument(new sfServiceReference('qux'));

// Alternative method, using the current init($qux) method
// Look! No factory required!
$container->register('altFoobar', 'Foobar')
          ->addMethodCall('init', array(new sfServiceReference('qux')));
Run Code Online (Sandbox Code Playgroud)