[英]What does a domain object factory look like?
我有一个DataMapperFactory
,我认为我正确地做了它,有一个但我有一个DomainObjectFactory
也有意义,但它似乎毫无意义。 就是这个:
namespace libs\factories;
use models as Models;
class DomainObjectFactory {
public function build($name) {
$className = 'Models\\' . $name;
return new className();
}
}
我能看到的唯一优势是我保持new
运算符不会出现在我的代码中。
DomainObjectFactory
要比这更多吗?
任何帮助都会非常感谢。
使用工厂有很多主要原因:
在单元测试方面,这是架构中最有用的结构之一。 让工厂负责创建实例会使测试时更容易引入模拟。
此外,作为额外的好处,您不再与您使用的类的名称紧密耦合。
在这里,您必须考虑两个方面。 首先 - 基于某些条件实例化不同对象的能力 - 在helmbert的答案中已经很好地描述了(对他而言+1) 。
另一种情况是在实例化域对象时,这更复杂。 像这样的东西:
$employees = new EmployeeCollection;
$address = new Location;
$class = $type . `Company`;
$company = new $class( $employee, $address );
在创建HoldingCompany
实例之前,还有很多工作要做。 但这整个过程可以在工厂完成。 特别是如果您的域对象工厂充分利用正确实现的DIC(这是非常罕见的,顺便说一句)。
你永远不应该在构造函数中进行任何计算。 这使得无法测试该代码。 构造函数应该只包含简单的变量赋值。
但是这引入了一个问题:有时你需要做一些逻辑操作,然后才能让其他代码结构处理你的实例化对象。 作为初学者,我们通常在构造函数中执行此操作。 但现在放在哪里?
这是工厂拯救的地方。
public function create( $name )
{
$instance = new $name;
if ( is_callable($instance, false, 'prepare') )
{
$instance->prepare();
}
return $instance;
}
现在,当您使用$factory->create('foobar')
,您的对象已完全准备好使用。
通常,您可以使用工厂从特定实现中抽象出来。 如果使用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.
当这变得非常有用时,一个用例(很多)是在进行单元测试时。 在测试驱动开发中,您经常使用模拟对象 (实现特定接口但实际上没有做任何事情的对象)替换类的依赖关系。 使用工厂模式,使用模拟类透明地替换特定类很容易。
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
词。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.