質問

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. 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.

There has to be more to a DomainObjectFactory than this right?

Any help would be great thanks.

役に立ちましたか?

解決 2

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. If you want to interchange this class with another implementation at a later time, you will have to manually change every new statement.

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.

他のヒント

There are there major reasons to use factories:

1. Abstract the creation of object

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

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).

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. 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).

3. Prepare objects before they are released in the application

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.


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.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top