原型模式
目的
为了避免以标准方式创建对象(如:new Foo()
)带来的成本,原型模式是通过创建对象的原型并克隆它的方式来创建对象。
使用场景
- 一次性创建大量的数据(例如:在数据库中,通过 ORM 一次性创建 1,000,000 条数据)
UML 类图

代码
BookPrototype.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <?php declare(strict_types = 1);
namespace DesignPatterns\Creational\Prototype;
abstract class BookPrototype { protected string $title; protected string $category;
abstract public function __clone();
public function getTitle(): string { return $this->title; }
public function setTitle(string $title) { $this->title = $title; } }
|
BarBookPrototype.php
1 2 3 4 5 6 7 8 9 10 11 12
| <?php declare(strict_types = 1);
namespace DesignPatterns\Creational\Prototype;
class BarBookPrototype extends BookPrototype { protected string $category = 'Bar';
public function __clone() { } }
|
FooBookPrototype.php
1 2 3 4 5 6 7 8 9 10 11 12
| <?php declare(strict_types = 1);
namespace DesignPatterns\Creational\Prototype;
class FooBookPrototype extends BookPrototype { protected string $category = 'Foo';
public function __clone() { } }
|
测试
Tests/PrototypeTest.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| <?php declare(strict_types = 1);
namespace DesignPatterns\Creational\Prototype\Tests;
use DesignPatterns\Creational\Prototype\BarBookPrototype; use DesignPatterns\Creational\Prototype\FooBookPrototype; use PHPUnit\Framework\TestCase;
class PrototypeTest extends TestCase { public function testCanGetFooBook() { $fooPrototype = new FooBookPrototype(); $barPrototype = new BarBookPrototype();
for ($i = 0; $i < 10; $i++) { $book = clone $fooPrototype; $book->setTitle('Foo Book No ' . $i); $this->assertInstanceOf(FooBookPrototype::class, $book); }
for ($i = 0; $i < 5; $i++) { $book = clone $barPrototype; $book->setTitle('Bar Book No ' . $i); $this->assertInstanceOf(BarBookPrototype::class, $book); } } }
|