不确定我的标题是否正确,因为我甚至不确定我使用的是正确的条款。
我有一个具有属性对象的类。设置此属性时,必须创建对象。我的问题是如何在没有紧耦合的情况下做到这一点?
示例:
class A
{
protected $_depending;
protected $_somePropertyObject;
public function __construct(\Lib\Dependency $depending)
{
$this->_setDepending($depending);
}
protected function _setDepending(\Lib\Dependency $depending)
{
$this->_depending = $depending;
}
public function setSomeProperty($someProperty)
{
// I want to prevent this
$this->_somePropertyObject = new \Lib\some\Object($someProperty);
}
}
我可以通过构造传递所需的对象,但需要做些什么呢?
如果我理解正确的工厂模式,那会有什么变化?我还需要在某处创建对象吗?不是对象本身而是工厂。紧耦合?对我来说似乎无穷无尽。当重新分解类时,它会被隔离在哪里以及如何制作类。
如果我将setSomeProperty函数设置为只接受\ Lib \ some \ Object,那么仍然需要由传递它的父对象创建。似乎只是改变创建它的位置?
希望我对自己要问的内容足够清楚。
提前致谢!
编辑我要问的是创建时间,地点,原因的顺序。
答案 0 :(得分:4)
依赖注入模式中工厂的目的是为另一个实例生成实例,而其他实例不需要知道如何生成它。
其核心是“工厂”只是一个对象返回者:在调用时返回实例的东西。
这在更有能力的语言中更容易看到。例如,在Python中,类是可调用的(没有new
运算符),并且调用类会生成类的实例。因此,如果类不需要参数,那么类可以是它们自己的工厂。同样,任何返回实例的零参数函数都可以视为工厂。这使得依赖注入非常清晰,并且没有样板。
在更严格的语言中(Java / C ++ / C#静态类型传统,或者类或函数不像PHP那样完全是第一类),你需要隐藏“模式”背后的依赖注入,因为{{3 }}。在PHP 5.3+中,您可以使用闭包作为工厂,或者您可以使用Java / C#方式并为每个工厂定义FactoryInterface
和新类。
例如,对于您的班级,您可以这样做:
class Aprime extends A
{
public function setSomeProperty($somePropertyFactory)
{
$this->_somePropertyObject = $somePropertyFactory();
}
}
在这个类中,setSomeProperty
需要一个零参数可调用的“工厂”,你可以这样产生:
$other_dep_factory = function(){ return new SomeOtherClass(); };
或者像这样:
class ClassFactory {
function __construct($classname, $args=array()) {
$this->class = new ReflectionClass($classname);
$this->args = $args;
}
function __invoke() {
return $this->class->newInstanceArgs($this->args);
}
}
$other_dep_factory = new ClassFactory('SomeOtherClass');
在PHP 5.3之前,你需要像Java那样:
interface IObjectFactory {
function getObject();
}
// this B-and-D interface is optional
// it has no body because PHP doesn't support
// type-hinting return values
interface ISomeOtherClassFactory {}
class SomeOtherClassFactory implements ISomeOtherClassFactory {
function getObject() {
return new SomeOtherClass();
}
}
class Aprime extends A
{
public function setSomeProperty(ISomeOtherClassFactory $somePropertyFactory)
{
$this->_somePropertyObject = $somePropertyFactory->getObject();
}
}
$other_dep_factory = new SomeOtherClassFactory();
$myAprimeObject->setSomeProperty($other_dep_factory);
那么你什么时候使用工厂?每当一个对象需要创建另一个对象时。如果对象只需使用另一个对象,只需传入一个实例。
答案 1 :(得分:0)
当您需要收集“信息”以创建存储在$ _somePropertyObject中的对象时,我喜欢使用工厂模式。例如,假设您必须为某些属性赋值以实例化它,或者在实例化之后立即运行几个方法。
此外,您还需要考虑是否需要稍后更改继承树。如果您现在可能正在为$ _somePropertyObject指定一个\ Lib \ some \ Object,您可能会发现自己希望以后可以轻松地将其换出\ Lib \ some \ FancyObject。如果使用依赖注入,则可以轻松交换子类型。
这是一本入门书:http://net.tutsplus.com/tutorials/php/the-whens-and-whys-for-php-design-patterns/