Шаблоны ООП на PHP: шаблон prototype

6 марта, 2023

Прототип — это порождающий паттерн проектирования, который позволяет копировать объекты, не вдаваясь в подробности их реализации

<?php

/**
 * Пример класса, имеющего возможность клонирования. Мы посмотрим как происходит
 * клонирование значений полей разных типов.
 */
class Prototype
{
    public $primitive;
    public $component;
    public $circularReference;

    /**
     * PHP имеет встроенную поддержку клонирования. Вы можете «клонировать»
     * объект без определения каких-либо специальных методов, при условии, что
     * его поля имеют примитивные типы. Поля, содержащие объекты, сохраняют свои
     * ссылки в клонированном объекте. Поэтому в некоторых случаях вам может
     * понадобиться клонировать также и вложенные объекты. Это можно сделать
     * специальным методом clone.
     */
    public function __clone()
    {
        $this->component = clone $this->component;

        // Клонирование объекта, который имеет вложенный объект с обратной
        // ссылкой, требует специального подхода. После завершения клонирования
        // вложенный объект должен указывать на клонированный объект, а не на
        // исходный объект.
        $this->circularReference = clone $this->circularReference;
        $this->circularReference->prototype = $this;
    }
}

class ComponentWithBackReference
{
    public $prototype;

    /**
     * Обратите внимание, что конструктор не будет выполнен во время
     * клонирования. Если у вас сложная логика внутри конструктора, вам может
     * потребоваться выполнить ее также и в методе clone.
     */
    public function __construct(Prototype $prototype)
    {
        $this->prototype = $prototype;
    }
}


$p1 = new Prototype();
$p1->primitive = 245;
$p1->component = new \DateTime();
$p1->circularReference = new ComponentWithBackReference($p1);

$p2 = clone $p1;
if ($p1->primitive === $p2->primitive) {
    echo "Primitive field values have been carried over to a clone. Yay!\n";
} else {
    echo "Primitive field values have not been copied. Booo!\n";
}
if ($p1->component === $p2->component) {
    echo "Simple component has not been cloned. Booo!\n";
} else {
    echo "Simple component has been cloned. Yay!\n";
}

if ($p1->circularReference === $p2->circularReference) {
    echo "Component with back reference has not been cloned. Booo!\n";
} else {
    echo "Component with back reference has been cloned. Yay!\n";
}

if ($p1->circularReference->prototype === $p2->circularReference->prototype) {
    echo "Component with back reference is linked to original object. Booo!\n";
} else {
    echo "Component with back reference is linked to the clone. Yay!\n";
}

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *