前言

昨天看的是对象对象池模式,主要应用场景是用在创建对象比较消耗时跟消耗系统资源时。大概原理是新建一个类继承 \Countable 其中有两私有属性,一个用来保存新建的对象当做对象池,另一个用来计数。当对象池内对象数量少于某个数目时,就创建对象。否则就从对象池中取一个对象,相应数量减一。

目的

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

示例

大数据量(例如:通过 ORM 模型一次性往数据库差入 100000条数据)。

UML 图

代码

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

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

}
}

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

}
}

测试

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
Tests/PrototypeTest.php
<?php
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);
}
}
}