Прототип (англ. Prototype ) - позволяет создавать новые объекты на основе некоторого объекта-прототипа при этом совсем
необязательно знать, как необходимый объект устроен.
Пример, конечно не очень, но он покажет суть шаблона. Перед подачей, наши бургеры нужно сложить в коробки.
Создание коробки привычным путем через new
занимает много времени (в конструкторе мы эмулируем задержку в 1 секунду).
Если нужны 10 - это 10 секунд, 100 - 100 секунд и т.д. Что нам мешает сделать один общий объект, а дальше его клонировать?
BoxPrototype.php
<?php
namespace DesignPatterns\Creational\Prototype ;
/**
* Class BoxPrototype
* @package DesignPatterns\Creational\Prototype
*/
class BoxPrototype
{
/**
* @var string
*/
protected $title ;
/**
* BoxPrototype constructor.
*
* If TRUE === delay, init object created 1 sec.
*
* @param bool $delay
*/
public function __construct ( $delay = false )
{
if ( true === $delay ) {
sleep ( 1 );
}
}
/**
* All classes have the magic method __clone.
* Implement this method if you want to change the default behavior.
*/
public function __clone ()
{
}
/**
* @return string
*/
public function getTitle (): string
{
return $this -> title ;
}
/**
* @param string $title
*
* @return void
*/
public function setTitle ( string $title )
{
$this -> title = $title ;
}
}
Test case:
PrototypeTest.php
<?php
namespace DesignPatterns\Tests\Creational\Prototype ;
use DesignPatterns\Creational\Prototype\BoxPrototype ;
use PHPUnit_Framework_TestCase ;
class PrototypeTest extends PHPUnit_Framework_TestCase
{
public function testPerformanceGetBoxWithDelay ()
{
$start = $this -> getTime ();
for ( $i = 0 ; $i < 15 ; $i ++ ) {
$box = new BoxPrototype ( true );
$box -> setTitle ( 'BOX#' . $i );
$this -> assertInstanceOf ( 'DesignPatterns\Creational\Prototype\BoxPrototype' , $box );
}
$finish = $this -> getTime ();
return $finish - $start ;
}
/**
* @depends testPerformanceGetBoxWithDelay
*
* @param int $testPerformanceInitWithNew
*/
public function testPerformanceGetBoxWithClone ( int $testPerformanceInitWithNew )
{
$start = $this -> getTime ();
$boxPrototype = new BoxPrototype ( true );
for ( $i = 0 ; $i < 15 ; $i ++ ) {
$box = clone $boxPrototype ;
$box -> setTitle ( 'BOX#' . $i );
$this -> assertInstanceOf ( 'DesignPatterns\Creational\Prototype\BoxPrototype' , $box );
}
$finish = $this -> getTime ();
$testPerformanceInitWithClone = $finish - $start ;
$this -> assertGreaterThan ( $testPerformanceInitWithClone , $testPerformanceInitWithNew );
}
private function getTime ()
{
return ( int ) microtime ( true );
}
}