概念
先创建好一个原型对象,然后通过clone原型对象来创建新的对象。适用于大对象的创建,因为创建一个大对象需要很大的开销,如果每次new就会消耗很大,原型模式仅需内存拷贝即可。
角色
- Prototype:抽象原型角色,提供克隆方法的接口
- ConcertePrototype:具体的原型角色,实现克隆对象并返回克隆对象
- UsePrototype 原型角色的使用者
例子(深拷贝与浅拷贝)
Prototype.php
<?php
/**
* Created by IntelliJ IDEA.
* User: 何晓宏
* Date: 2018/10/14
* Time: 1:18
*/
namespace PrototypePattern;
interface Prototype{
//浅拷贝,只拷贝当前对象实例不拷贝引用的对象
public function shallowCopy();
//深拷贝,把拷贝的对象引用的对象也拷贝,利用序列化serialize来做拷贝
public function deepCopy();
}
ConcertePrototype.php
<?php
/**
* Created by IntelliJ IDEA.
* User: 何晓宏
* Date: 2018/10/14
* Time: 1:20
*/
namespace PrototypePattern;
class ConcretePrototype implements Prototype{
private $_name;
public function __construct($name)
{
$this->_name=$name;
}
public function setName($name)
{
$this->_name=$name;
}
public function getName()
{
return $this->_name;
}
public function shallowCopy()
{
return clone $this;
}
/**
* 深拷贝对象
* @return mixed $clone_obj
* serialize序列化--把对象写到流里的过程
* unserialize反序列化--吧对象从流里读出来
*
*/
public function deepCopy()
{
$serialize_obj=serialize($this);
$clone_obj=unserialize($serialize_obj);
return $clone_obj;
}
}
UsePrototype.php
class Demo
{
public $string;
}
class UsePrototype
{
public function shallow()
{
$demo = new Demo();
//浅拷贝,只拷贝当前对象实例(基本类型的数据)不拷贝引用的对象
$demo->string = "1";
$object_shallow_first = new ConcretePrototype($demo);
//object_shallow_second拷贝object_shallow_first的值
$object_shallow_second = $object_shallow_first->shallowCopy();
//第一次输出
var_dump($object_shallow_first->getName());
echo '<br/>';
var_dump($object_shallow_second->getName());
echo '<br/>';
//浅拷贝没有开辟新的空间,指向的是相同的地址,第二次输出相同
$demo->string = "2";
var_dump($object_shallow_first->getName());
echo '<br/>';
var_dump($object_shallow_second->getName());
echo '<br/>';
}
public function deep()
{
$demo = new Demo();
$demo->string = "1";
$object_deep_first = new ConcretePrototype($demo);
//object_shallow_second拷贝object_shallow_first的对象
$object_deep_second = $object_deep_first->deepCopy();
var_dump($object_deep_first->getName());
echo '<br/>';
var_dump($object_deep_second->getName());
echo '<br/>';
//由于深拷贝开辟了新的地址存放对象,两者的地址不一样输出的值也不一样
$demo->string = "2";
var_dump($object_deep_first->getName());
echo '<br/>';
var_dump($object_deep_second->getName());
echo '<br/>';
}
}
$object = new UsePrototype();
$object->shallow();
echo '<hr>';
$object->deep();