简体   繁体   English

域对象工厂是什么样的?

[英]What does a domain object factory look like?

I have a DataMapperFactory and I think I am doing it correctly and it makes sense to have one but I have a DomainObjectFactory too but it just seems pointless. 我有一个DataMapperFactory ,我认为我正确地做了它,有一个但我有一个DomainObjectFactory也有意义,但它似乎毫无意义。 This is it: 就是这个:

namespace libs\factories;
use models as Models;

class DomainObjectFactory {

    public function build($name) {

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

        return new className();

    }

}

The only advantage I can see of this is that I am keeping the new operator from being present all over my code. 我能看到的唯一优势是我保持new运算符不会出现在我的代码中。

There has to be more to a DomainObjectFactory than this right? DomainObjectFactory要比这更多吗?

Any help would be great thanks. 任何帮助都会非常感谢。

There are there major reasons to use factories: 使用工厂有很多主要原因:

1. Abstract the creation of object 1.摘要对象的创建

This is one of the most useful structures in your architecture when it comes to unit testing. 在单元测试方面,这是架构中最有用的结构之一。 Having a factory be responsible for the creation of instance makes easier to introduce mocks when testing. 让工厂负责创建实例会使测试时更容易引入模拟。

Also, as added benefit, your is not anymore tightly coupled to the name of the classes that you utilize. 此外,作为额外的好处,您不再与您使用的类的名称紧密耦合。

2. Simplify instantiation 2.简化实例化

Here you have two aspect that you have to consider. 在这里,您必须考虑两个方面。 First - the ability to instantiate different objects based on some condition - was already quite well described in helmbert's answer (+1 for him) . 首先 - 基于某些条件实例化不同对象的能力 - 在helmbert的答案中已经很好地描述了(对他而言+1)

The other case is when you are instantiating domain objects, which more complex. 另一种情况是在实例化域对象时,这更复杂。 Something like this: 像这样的东西:

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

There is quite a lot to do before you can create an instance of HoldingCompany . 在创建HoldingCompany实例之前,还有很多工作要做。 But this whole process can be done withing the factory. 但这整个过程可以在工厂完成。 Especially if your domain object factory makes a good use of correctly implemented DIC (which is quite rare, btw). 特别是如果您的域对象工厂充分利用正确实现的DIC(这是非常罕见的,顺便说一句)。

3. Prepare objects before they are released in the application 3.在对象在应用程序中释放之前准备对象

You should never do any computation in the constructor. 永远不应该在构造函数中进行任何计算。 It make impossible to test that code. 这使得无法测试该代码。 Constructors should only contains simple variable assignments. 构造函数应该只包含简单的变量赋值。

But this introduces an issue: sometimes you need to do few logical operations, before you can let other code structures to deal with your instantiated object. 但是这引入了一个问题:有时你需要做一些逻辑操作,然后才能让其他代码结构处理你的实例化对象。 As beginners we usually do that in the constructor. 作为初学者,我们通常在构造函数中执行此操作。 But where to put it now? 但现在放在哪里?

This is where factories come to the rescue. 这是工厂拯救的地方。

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

Now, when you use $factory->create('foobar') , your object is fully primed to be used. 现在,当您使用$factory->create('foobar') ,您的对象已完全准备好使用。


In general, you can use the factory to abstract from specific implementations. 通常,您可以使用工厂从特定实现中抽象出来。 If you use the new <classname> operator, you instantiate a specific class every time. 如果使用new <classname>运算符,则每次都实例化一个特定的类。 If you want to interchange this class with another implementation at a later time, you will have to manually change every new statement. 如果要在以后将此类与其他实现交换,则必须手动更改每个new语句。

The factory pattern allows you to abstract from specific classes. 工厂模式允许您从特定类中抽象 A valid minimal use case might be something like this: 有效的最小用例可能是这样的:

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.

One use case (of many) when this becomes extremely useful is when working with unit tests. 当这变得非常有用时,一个用例(很多)是在进行单元测试时。 In Test-Driven Development, you often replace dependencies of classes with mock objects (objects that implement a certain interface, but don't really do anything). 在测试驱动开发中,您经常使用模拟对象 (实现特定接口但实际上没有做任何事情的对象)替换类的依赖关系。 Using the factory pattern, it is quite easy to transparently substitute specific classes with mock classes. 使用工厂模式,使用模拟类透明地替换特定类很容易。

public function build($name) {

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

        return new $className();
}

That would work for you. 这对你有用。

Defining object factories is a good practice, when you would like to set some default properties to objects, and also, you will not have to worry in what namespace or directory some class exists. 定义对象工厂是一种很好的做法,当您想要为对象设置一些默认属性时,您也不必担心某些类存在于哪个命名空间或目录中。

Example: 例:

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

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

You just make default objects so quickly via such factories, besides keeping word new away. 你只需要通过这些工厂快速制作默认对象,除了保持new词。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM