2010-08-05 54 views
1

那么,工厂模式是否合适?

我有一个问题(好吧,没有真正的问题,但我想尝试一些新的东西)与创建对象。其实我有一些订单,其中包含一个订购项目列表。

这些订单项已在整个应用程序中使用,因此我需要一种方法来创建它们。主要的问题是,我希望能够以许多不同的方式创建这些对象。

其实我在类的构造函数中执行此操作,并检查给定的参数。 (我使用PHP,所以从你一定会知道:)语言没有超载支持)

一个简单而快速的例子

class foo { 
    protected $_data=null; 
    public function __contruct($bar){ 
     if (is_array($bar)){ 
      $this->_data=$bar; 
     } 
     else { 
      $dataFromDb=getDataFromDatabase 
      $this->_data=$dataFromDb; 
     } 
    } 
} 

无论如何,如果我想创建我的对象给出另一种类型的参数,可以说一个封装在字符串中的xml文档,我需要将所有这些东西放在我的构造函数中。 如果创建对象的过程更复杂,我最终需要为每种类型创建一个单独的方法,我想启动。但是只有在创建这种特殊类型时才会调用此方法。 (我认为你有问题:))

另一个问题想到,如果我需要在构造函数中创建具体对象的更多参数,我修改了所有我的代码,导致构造器改变。 (好吧,我可以给他更多的参数并使用默认值,但这不是我真正想要的)。

所以我的问题是,哪种模式适合这个问题来解决我创建一个具体的对象。我想为每一种我想要创建具体对象的方式创建一个工厂。但我不确定这是否是解决此类问题的常见解决方案。

回答

2

IF改变我会做它像这样(一拉Zend框架的通用构造函数)的构造其唯一的签名:

class foo { 
    // params 

    public function __construct($options = null) 
    { 

    if(null !== $options) 
    { 
     $this->setOptions($options); 
    } 
    } 

    public function setOptions(array $options){ 

    foreach ($options as $name => $value){ 
     $method = 'set' . $name; 
     if(method_exists($this, $method) 
     { 
     $this->$method($value); 
     } 
    } 

    return $this; 
    } 
} 

这essntially意味着所有构造函数参数数组元素与名为键,以及在初始化过程中你想要在这个数组中使用的任何东西,你创建一个setter,然后自动调用它。缺点是在IDE中缺乏有效的暗示。

。如果您想拥有特定的构造函数的话,我可能会用一个工厂去,但仍是otherhand使用大致相同的方法:

class foo { 

    public static function create($class, $options) 
    { 
    if(class_exists($class)) 
    { 
     $obj = new $class($options); 
    } 
    } 
} 

当然,你可以选择使用PHP的反射来确定如何调用构造函数而不是仅仅注入任意数组参数。

+0

哇,例如一个代码是非常好的。花了我一段时间来理解它,但我会明确地使用它,如果它匹配我得到的任何问题。 但在具体的情况下,我认为你的第二个例子是我想要这样做的方式。 所以我创建了一个我当前的抽象基类,并在每个我想要创建对象的方式中执行分离类中的具体事情。 谢谢你,你的例子真的让我很开心。 – evildead 2010-08-05 22:44:19

+0

很高兴帮助...请不要我改变构造函数一点...我很早就着急了:-) – prodigitalson 2010-08-05 23:25:23

+0

我瞎了,什么改变了? – evildead 2010-08-05 23:36:48

1

你可以简单地使它与可选PARAMS工厂:)

class Example_Factory 
{ 
    public static function factory($mandatoryParam, $optionalParam = null) 
    { 
     $instance = new self; 
     $instance->setMandatory($mandatoryParam); 

     if ($optionalParam !== null) { 

      $instance->setOptional($optionalParam); 
     } 

     return $instance; 
    } 

    public function setMandatory($in) 
    { 
     // do something.... 
    } 

    public function setOptional($in) 
    { 
     // do some more... 
    } 
} 
+0

也非常感谢你的回答。这也是一个很好的解决方案,但我认为我不能适应我的具体问题,因为我没有强制性和可选的东西。我赋予我的具体构造函数的值不能分成这两类。 – evildead 2010-08-05 22:49:28

+0

好吧,它不是强制性的/可选的,它只是一个例子,你也可以只有一个参数或5.模式是根据输入数据调用新实例的方法:) – 2010-08-05 23:06:17