2013-03-27 212 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