3

我有一个DataMapperFactory,我认为我做对了,有一个很有意义,但我也有一个DomainObjectFactory,但这似乎毫无意义。就是这个:

namespace libs\factories;
use models as Models;

class DomainObjectFactory {

    public function build($name) {

        $className = 'Models\\' . $name;

        return new className();

    }

}

我能看到的唯一优点是我可以防止new操作员出现在我的代码中。

必须有DomainObjectFactory比这更多的权利吗?

任何帮助都会非常感谢。

4

3 回答 3

6

使用工厂有几个主要原因:

1.抽象对象的创建

当涉及到单元测试时,这是架构中最有用的结构之一。让工厂负责实例的创建可以更容易地在测试时引入模拟。

此外,作为额外的好处,您不再与您使用的类的名称紧密耦合。

2.简化实例化

在这里,您必须考虑两个方面。首先 - 基于某些条件实例化不同对象的能力 - 在helmbert 的回答中已经很好地描述了 (+1 为他)

另一种情况是当您实例化域对象时,这更复杂。像这样的东西:

$employees = new EmployeeCollection;
$address = new Location;
$class = $type . `Company`;
$company = new $class( $employee, $address );

在创建HoldingCompany. 但是这整个过程可以在工厂内完成。特别是如果您的域对象工厂充分利用正确实现的 DIC(顺便说一句,这非常罕见)。

3. 在应用程序中释放对象之前准备它们

永远不应该在构造函数中进行任何计算。无法测试该代码。构造函数应该只包含简单的变量赋值。

但这引入了一个问题:有时您需要做一些逻辑操作,然后才能让其他代码结构来处理您的实例化对象。作为初学者,我们通常在构造函数中这样做。但是现在放在哪里呢?

这就是工厂来救援的地方。

public function create( $name )
{
     $instance = new $name;
     if ( is_callable($instance, false, 'prepare') )
     {
         $instance->prepare();
     }
     return $instance;
}

现在,当您使用 时$factory->create('foobar'),您的对象已完全准备好使用。


于 2013-02-19T19:46:09.643 回答
5

通常,您可以使用工厂从特定实现中抽象出来。如果使用new <classname>运算符,则每次都实例化一个特定的类。如果您想稍后将此类与另一个实现互换,则必须手动更改每个new语句。

工厂模式允许您从特定的类中抽象出来。一个有效的最小用例可能是这样的:

interface UserInterface {
    public function getName();
}

class UserImplementationA implements UserInterface {
    private $name;
    public function getName() { return $this->name; }
}

class UserImplementationB implements UserInterface {
    public function getName() { return "Fritz"; }
}

class UserFactory {
    public function createUser() {
        if (/* some condition */) return new UserImplementationA();
        else                      return new UserImplementationB();
    }
}

$f = new UserFactory();
$u = $f->createUser();   // At this point, you don't really have to care 
                         // whether $u is an UserImplementationA or
                         // UserImplementationB, you can just treat it as
                         // an instance of UserInterface.

当这变得非常有用时,一个(许多)用例是在使用单元测试时。在测试驱动开发中,您经常用模拟对象(实现特定接口但实际上不做任何事情的对象)替换类的依赖关系。使用工厂模式,很容易用模拟类透明地替换特定类。

于 2013-02-19T19:22:55.857 回答
1
public function build($name) {

        $className = 'Models\\' . $name;

        return new $className();
}

那对你有用。

定义对象工厂是一种很好的做法,当您想为对象设置一些默认属性时,您也不必担心某个类存在于哪个命名空间或目录中。

例子:

public function createButton($name){
    require("home/lib/display/Button.php") ;

    $button = new Button($name, "some default param") ;
    $button->visible = true ;
    return $button ;
}

除了保持消息外,您只需通过此类工厂如此快速地制作默认对象new

于 2013-02-19T19:11:39.657 回答