PHP设计模式(六)之PHP实现原型模式
一、什么是原型模式
原型模式:原型模式用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。
意图:复制已有对象,不用依赖所属类
二、使用原型模式的原因
1)普通方式创建对象通过new Xxx();如果每一次都通过new来创建一个对象,并且在new时还要进行初始化化工作,,它的开销非常大。
2)原型模式最大不同之处在于它是先创建好一个原型对象,然后通过clone这个原型对象来实现新对象的创建,如此省去了重复的初始化工作。
解释:
案例一:当厨师在做清蒸鲈鱼这道菜时,都有固定的步骤,每一步做什么,第二步做什么...当只有一个客户点了这道菜时,好吧,按照步骤做吧。当遇到酒席时,每一桌都有清蒸鲈鱼这道菜时,还按照第一步、第二步...来做,显然是无法完成任务的。那么厨师要怎么样才能完成任务?厨师就在想,每一个步骤是一样的,那能不能复制呢?当然可以了,于是厨师先不做清蒸鲈鱼了,先创建一个清蒸鲈鱼原型对象,然后批量生产。
案例二:《大话西游》中至尊宝对战牛魔王,至尊宝拔出猴毛生产出N多个自己,这也是原型模式。
三、原型模式结构
抽象原型角色(Prototype):声明一个克隆自身的接口
具体原型角色(Concrete Prototype):实现一个克隆自身的操作
四、深、浅拷贝
深拷贝:
被拷贝对象的所有的变量都含有与原来对象相同的值,除了那些引用其他对象的变量。那些引用其他对象的变量将指向一个被拷贝的新对象,而不再是原有那些被引用对象。
即深拷贝把要拷贝的对象所引用的对象也都拷贝了一次,而这种对被引用到的对象拷贝叫做间接拷贝。
浅拷贝:
拷贝对象的所有变量都含有与原对象相同的值,而且对其他对象的引用仍然是指向原来的对象。
即浅拷贝只负责当前对象实例,对引用的对象不做拷贝。
利用序列化来做深拷贝:
利用序列化来做深拷贝,把对象写到流里的过程是序列化(Serilization)过程,但在业界又将串行化这一过程形象的称为“冷冻”或“腌咸菜”过程;
而把对象从流中读出来的过程则叫做反序列化(Deserialization)过程,也称为“解冻”或“回鲜”过程。
在PHP中使用serialize和unserialize函数实现序列化和反序列化
五、代码实现
// 抽象原型角色(Prototype)
SteamedPerchPrototype.php
<?php
/**
* 清蒸鲈鱼原型 => 抽象原型角色
*
**/
interface SteamedPerchPrototype
{
// 浅复制
public function shallowCopy();
// 深复制
public function deepCopy();
}
// 具体原型角色(Concrete Prototype)
ConcreteSteamedPerchPrototype.php <?php
/**
* 具体清蒸鲈鱼原型 ==> 具体原型角色
*
**/
class ConcreteSteamedPerchPrototype implements SteamedPerchPrototype
{
// 清蒸鲈鱼
public $name;
// 初始化菜名
public function __construct($name)
{
$this->name = $name;
}
// 设置菜名
public function setName($name)
{
return $this->name = $name;
}
// 获取菜名
public function getName()
{
return $this->name;
}
// 实现浅复制
public function shallowCopy()
{
return clone $this;
}
// 实现深复制
public function deepCopy()
{
// 通过序列化实现深度复制
$serializeObj = serialize($this);
return unserialize($serializeObj);
}
}
SteamedPerch.php
<?php
class SteamedPerch
{
public $string;
}
// 实现
index.php
<?php
require_once './SteamedPerchPrototype.php';
require_once './ConcreteSteamedPerchPrototype.php';
require_once './SteamedPerch.php';
//$a = new ConcreteSteamedPerchPrototype('清蒸鲈鱼');
$SteamedPerchObj = new SteamedPerch();
$SteamedPerchObj->string = '鱼';
// 浅复制
$a = new ConcreteSteamedPerchPrototype($SteamedPerchObj);
$b = $a->shallowCopy();
var_dump($a->getName());
echo '<br>';
var_dump($b->getName());
echo '<br>';
// 深复制
$c = $a->deepCopy();
var_dump($c->getName());
echo '<br>';
$SteamedPerchObj->string = '1231231231';
$c = $a->deepCopy();
var_dump($c->getName());
我是夕阳何处寻,期待和优秀的你一起同行!
夕阳何处寻
2020年1月5日