1.5. 原型模式

1.5.1. 目的

避免以标准方式(new Foo())创建对象的成本,而是创建一个原型(prototype)并克隆它。

1.5.2. 例子

  • 大量数据(例如:通过 ORM 在数据库中创建百万行数据。)

1.5.3. UML 图

Alt Prototype UML Diagram

1.5.4. 代码

你可以在 GitHub 上找到这些代码

BookPrototype.php

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

BarBookPrototype.php

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

FooBookPrototype.php

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

1.5.5. 测试

Tests/PrototypeTest.php

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