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

2 回答 2

5

依赖注入模式中工厂的目的是为另一个实例生成实例,而另一个实例不需要知道如何生成它。

在其核心,“工厂”只是一个对象返回器:调用时返回一个实例的东西。

这在功能更强大的语言中更容易看到。例如,在 Python 中,类是可调用的(没有new运算符),调用一个类会产生该类的一个实例。因此,如果类不需要参数,则类可以是它们自己的工厂。同样,任何返回实例的零参数函数都可以被视为工厂。这使得依赖注入非常清晰且没有样板。

在更严格的语言中(Java/C++/C# 静态类型的传统,或者类或函数不像 PHP 那样完全是一流的),您需要掩盖“模式”背后的依赖注入,因为缺少“设计模式”语言特点。在 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);

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

于 2013-03-27T17:20:55.810 回答
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

于 2013-03-27T16:52:39.647 回答