Прототип (англ. 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 );
}
}