2013-03-27 205 views
3

不知道我的标题是否正确,因为我甚至不确定我是否使用了正确的术语。依赖注入和/或工厂模式

我有一个属性是一个对象的类。设置此属性时,必须创建对象。我的问题是如何在没有紧密耦合的情况下做到这一点?

例子:

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,那么仍然需要由传递它开始的父对象创建。似乎只是改变了它的创建位置?

希望我清楚自己想要问什么。

在此先感谢!

编辑我在问什么是什么时候,在哪里,为什么创建的顺序。

回答

4

在依赖注入模式的工厂的目的是产生实例的另一个实例,没有其他实例需要知道如何产生的。

在其核心,“工厂”只是一个对象返回者:当被调用时返回一个实例。

这更容易看到更多功能的语言。例如,在Python类中可以调用(没有new运算符),调用一个类将产生一个类的实例。所以如果类不需要参数,那么类可以是他们自己的工厂。同样,任何返回实例的零参数函数都可以被视为工厂。这使得依赖注入非常清晰且免费的样板。在更僵化的语言(Java/C++/C#静态类型的传统,或类或函数并不完全像PHP中的第一类)中,您需要隐藏“模式”后面的依赖注入,因为"design patterns" are missing language features。在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); 

那么你什么时候使用工厂?每当一个对象需要创建另一个对象时。如果对象只需要使用另一个对象,只需传入一个实例。

+0

但是我在哪里创建这个工厂对象?我应该将它作为依赖项传递吗?优选没有静电。 – John 2013-03-27 19:16:47

+0

在创建需要之前创建它。 – 2013-03-27 19:35:52

+0

那么它仍然紧密耦合?例如:public function something(){$ factory = new factory(); }?不要谈论制定者? – John 2013-03-27 19:52:45

0

当您需要收集“信息”来创建存储在$ _somePropertyObject中的对象时,我喜欢使用工厂模式。例如,假设您必须为某些属性赋值以实例化它或在实例化之后立即运行一些方法。

另外,您还需要考虑是否需要稍后更改继承树。如果您现在可能将$ _somePropertyObject指定为\ Lib \ some \ Object,您可能希望稍后可以轻松将其替换为\ Lib \ some \ FancyObject。如果你使用依赖注入,你可以很容易地交换子类型。

这里有一个引:http://net.tutsplus.com/tutorials/php/the-whens-and-whys-for-php-design-patterns/

此外,太:https://stackoverflow.com/a/2083455/1121827

+0

您在哪里制造工厂以及如何创建,定义和收集信息?来自第一堂课。 – John 2013-03-27 17:01:49

+0

看到您的编辑。我还在想知道在哪里创建工厂对象本身? – John 2013-03-27 17:15:21