原型模式(Prototype)

目的

相比正常创建一个对象 ( new Foo() ),首先创建一个原型,然后克隆它会更节省开销。

示例

  • 大数据量 ( 例如:通过 ORM 模型一次性往数据库插入 1,000,000 条数据 ) 。

UML 图

file

代码

完整代码请看 GitHub

BookPrototype.php

  1. <?php
  2. namespace DesignPatterns\Creational\Prototype;
  3. abstract class BookPrototype
  4. {
  5. /**
  6. * @var string
  7. */
  8. protected $title;
  9. /**
  10. * @var string
  11. */
  12. protected $category;
  13. abstract public function __clone();
  14. public function getTitle(): string
  15. {
  16. return $this->title;
  17. }
  18. public function setTitle($title)
  19. {
  20. $this->title = $title;
  21. }
  22. }

BarBookPrototype.php

  1. <?php
  2. namespace DesignPatterns\Creational\Prototype;
  3. class BarBookPrototype extends BookPrototype
  4. {
  5. /**
  6. * @var string
  7. */
  8. protected $category = 'Bar';
  9. public function __clone()
  10. {
  11. }
  12. }

FooBookPrototype.php

  1. <?php
  2. namespace DesignPatterns\Creational\Prototype;
  3. class FooBookPrototype extends BookPrototype
  4. {
  5. /**
  6. * @var string
  7. */
  8. protected $category = 'Foo';
  9. public function __clone()
  10. {
  11. }
  12. }

测试

Tests/PrototypeTest.php

  1. <?php
  2. namespace DesignPatterns\Creational\Prototype\Tests;
  3. use DesignPatterns\Creational\Prototype\BarBookPrototype;
  4. use DesignPatterns\Creational\Prototype\FooBookPrototype;
  5. use PHPUnit\Framework\TestCase;
  6. class PrototypeTest extends TestCase
  7. {
  8. public function testCanGetFooBook()
  9. {
  10. $fooPrototype = new FooBookPrototype();
  11. $barPrototype = new BarBookPrototype();
  12. for ($i = 0; $i < 10; $i++) {
  13. $book = clone $fooPrototype;
  14. $book->setTitle('Foo Book No ' . $i);
  15. $this->assertInstanceOf(FooBookPrototype::class, $book);
  16. }
  17. for ($i = 0; $i < 5; $i++) {
  18. $book = clone $barPrototype;
  19. $book->setTitle('Bar Book No ' . $i);
  20. $this->assertInstanceOf(BarBookPrototype::class, $book);
  21. }
  22. }
  23. }