Шаблон Prototype (Прототип)

03-11-2019Время чтения ~ 2 мин.PHP/ООП 6119

Прототип — порождающий шаблон проектирования. Он используется для клонирования существующего объекта, вместо его инстанцирования с помощью new. Нам повезло, что в PHP уже есть всё необходимое для Prototype — это языковая конструкция clone, которая позволяет упростить реализацию праттерна до одной строчки.

Вообще может возникнуть вопрос, зачем вообще нужно клонирование, разве недостаточно обычного присваивания через равно «=»? Покажу на практическом примере.

Пусть у нас будет простой класс A с полем $val и двумя методами: один для установки значения поля, другой для его вывода.

 class A {	private $val;	public function set($val)	{	$this->val = $val;	}	public function out()	{	echo $this->val;	} } 

Теперь проверим как он работает:

 // создаем объект $a = new A; // устанавливаем внутреннее поле $a->set('hello'); // вывод $a->out(); // hello 

Всё вполне ожидаемо. Теперь попробуем сделать копию объекта $a с помощью присваивания. Проверим что выводится в этом случае.

 // получаем новую переменную $b $b = $a; // работаем с $b $b->set('hi'); $b->out(); // hi // проверяем что в $a $a->out(); // hi 

Неожиданно, так? Мы изменили объект $b, но он поменял и состояние поля в $a.

Так вот — в PHP операция присваивания объекта происходит по ссылке. То есть строчка $b = $a; не создала новый объект, а лишь указала, что $b ссылается на уже существующий $a. Поэтому все операции с этими переменными происходят с единым объектом.

Но что же делать, если действительно требуется создать совершенно новый объект/переменную? В PHP используется clone.

 // создаем объект $a = new A; // устанавливаем внутреннее поле $a->set('hello'); // вывод $a->out(); // hello // клонирование $c = clone $a; // устанавливаем свой вариант $c->set('hi'); // проверяем $c->out(); // hi $a->out(); // hello 

Здесь переменная $c создана через клонирование другого объекта и после этого PHP будет считать их совершенно разными и несвязанными между собой.

Пример кода я разместил на гитхабе.

Клонирование может использоваться для случаев, когда нужно создать несколько объектов, инстанцирование которых затратная операция. В этом случае вначале делается один объект, происходит его начальная «тяжелая инициализация», а после объект клонируется для использования под разные задачи. Следует отметить, что в PHP копирование по ссылке для объектов сделано с целью оптимизации памяти, поскольку классы — достаточно сложные типы данных, которые требуют особого обращения. Поэтому клонирование — это способ быстрого получения отдельной копии, но за счёт дополнительного расхода памяти.

Похожие записи