【问题标题】:Not understanding how factory pattern works不了解工厂模式的工作原理
【发布时间】:2015-12-14 02:25:09
【问题描述】:

我创建了一个抽象工厂类,其中包含一个将工厂创建的所有对象存储在数组中的方法。

abstract class ItemFactory{

   function __construct($default_item){

       $this->default_item = $default_item;
   }

   // Returns a new item + add the item to the factory items collection
   function createFactoryItem(){

       $this->addFactoryItem($object = clone $this->default_item);

       return $object;
   }

   // Add the item to the collection of items created with the factory
   function addFactoryItem($item_obj){

       $this->items[] = $item_obj;

       return $this;
   }
}

ElementFactory 类扩展了 ItemFactory,SubElement 也是如此。

class ElementFactory extends ItemFactory{

    function __construct(){
        parent::__construct(new Element(new SubElement())));
    }
}

我目前对下面示例中这种工厂模式的行为感到困惑。

$element_factory = new ElementFactory();

$element_factory->createFactoryItem()->setElementId(1);

$element_factory->createFactoryItem()->setElementId(2);

// Here I create a variable that stores the third element created from the factory
// setElementId() method belongs to Element and return $this
$element_3 = $element_factory->createFactoryItem()->setElementId(3);

// Here the part creating weird results
$element_3->getSubElementFactory()->createFactoryItem();

var_dump($element_factory);

我的预期是这样的:

ElementFactory Items:
Array
[0]: Element 1
[1]: Element 2
[2]: Element 3
     '-- [0] : SubElement 1

Instead I get this:
[0]: Element 1
     '-- [0] : SubElement 1
[1]: Element 2
     '-- [0] : SubElement 1
[2]: Element 3
     '-- [0] : SubElement 1

我创建了一个单独的变量来存储工厂创建的第三个对象,并且仅对第三个元素调用 getSubElementFactory()->createFactoryItem() 方法:为什么仍将 SubElement 对象添加到所有工厂元素在第三个而已

非常感谢您的帮助

【问题讨论】:

    标签: php oop factory


    【解决方案1】:

    我怀疑这与其说是工厂,不如说是收藏。

    话虽如此,我认为您的问题不在于模式,而在于克隆。

    在 PHP 中,clone 不是深拷贝。

    根据为ElementFactory 提供的示例,您可能将SubElement 设置为元素类的成员变量。

    此克隆不跟随此链接并创建子元素的新副本。它将创建元素的新副本,但副本将复制指向与原始元素相同的SubElement 的指针。

    这意味着在一个上调用getSubElementFactory 与在另一个上调用它是一样的。从而产生了三副本的错觉。

    您可以做的是在您的类中添加一个__clone 方法。此方法必须创建一个新的SubElement。 (也克隆它?)。

    这将提供所需的行为。

    【讨论】:

    • 非常感谢这个伟大的洞察力,我在 ElementFactory 中添加了function __clone(){ $this->default_item = clone $this->default_item; return $this->default_item; } 但最终结果是一样的,我是否正确实施了深层复制?
    • 没关系,我在工厂中设置了__clone,而不是在工厂制造的项目类中设置它。非常感谢您让我走上正轨。
    • __clone 方法允许作者编写深拷贝算法。或者至少有助于标准化此类代码。
    猜你喜欢
    • 2011-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-20
    • 2012-12-11
    • 2011-02-18
    • 2018-02-17
    相关资源
    最近更新 更多