我正在尝试为我们的系统设计一组工厂类,其中一些由工厂创建的对象也需要初始化,然后才能正确使用它们。

例子:

$foobar = new Foobar();
$foobar->init( $qux, ... );
// $foobar ready for usage

对于同一示例,可以说$qux对象是Foobar所需的唯一依赖项。我想要得到的是:
$foobar = Foo_Factory( 'bar' );

为了避免在整个系统中传递$qux对象并将其作为另一个参数传递给factory类,我想直接在factory类中执行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;
    }

}

想到的解决方案很少,但都不是理想的解决方案:
  • $qux的静态setter方法添加到工厂类,并将其对$qux的引用存储在私有(private)静态变量中。系统可以在开始时设置$qux,并且工厂类可以防止将来发生任何更改(出于安全原因)。尽管这种方法行得通,但在单元测试期间使用静态参数存储对$qux的引用还是有问题的(例如,幸福地生活在两次测试之间)由于其静态,因此需要进行个别测试)。
  • 使用Singleton模式创建一个新的上下文类,并让factory类使用它来获取对$qux的引用。这可能比选项#1干净一些(尽管我们将静态问题从工厂类移到了上下文类)。
  • 完全使用依赖项注入(inject),即,将$qux传递给使用factory类的任何对象,然后将该对象作为另一个参数传递给factory类:Foo_Factory::getFoo($type, $qux);
  • 与上面的(#3)相同,但是不要在系统中传递$qux,而是传递factory类的实例(即,在这种情况下,它不是静态的,而是可实例化的)。

  • 您会推荐什么?上面提到的四种选择中的任何一种,还是有更好的方法来做到这一点?

    注意:我不想在这里陷入static is evil的大战,只是想提出最好的解决方案。

    最佳答案

    我将一路使用Dependency Injection。但是,与其在各处传递$ qux,不如在Dependency Injector容器中注册它,然后让该容器对其进行整理。用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')));
    

    关于php - 带对象初始化的工厂类-尝试避免静态,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/5486921/

    10-10 00:10