https://www.cnblogs.com/ddddemo/p/5623213.html
概念理解:原型模式是先创建好一个原型对象,然后通过clone原型对象来创建新的对象。适用于大对象的创建,因为创建一个大对象需要很大的开销,如果每次new就会消耗很大,原型模式仅需内存拷贝即可。
主要角色:
Prototype(抽象原型角色):声明一个克隆自身的接口
Concrete Prototype(具体原型角色):实现一个克隆自身的操作
下面我们观察源码:
\Libs\Prototype.php
<?php
namespace Libs;
interface Prototype
{
public function shallowCopy();
public function deepCopy();
}
\Libs\ConcretePrototype.php
<?php
namespace Libs;
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;
}
/**
* 深拷贝
* */
public function deepCopy()
{
$serialize_obj = serialize($this);
$clone_obj = unserialize($serialize_obj);
return $clone_obj;
}
}
\Libs\UsePrototype.php
<?php
namespace Libs;
class Demo
{
public $string;
}
class UsePrototype
{
public function shallow()
{
$demo = new Demo();
$demo->string = "susan";
$object_shallow_first = new ConcretePrototype($demo);
$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 = "sacha";
var_dump($object_shallow_first->getName());
echo '<br/>';
var_dump($object_shallow_second->getName());
echo '<br/>';
}
public function deep()
{
$demo = new Demo();
$demo->string = "Siri";
$object_deep_first = new ConcretePrototype($demo);
$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 = "Demo";
var_dump($object_deep_first->getName());
echo '<br/>';
var_dump($object_deep_second->getName());
echo '<br/>';
}
}
调用:
$up = new \Libs\UsePrototype; $up->shallow(); echo ‘<hr>’; $up->deep();
结果:
object(Libs\Demo)#2 (1) { [“string”]=> string(5) “susan” } object(Libs\Demo)#2 (1) { [“string”]=> string(5) “susan” } object(Libs\Demo)#2 (1) { [“string”]=> string(5) “sacha” } object(Libs\Demo)#2 (1) { [“string”]=> string(5) “sacha” } object(Libs\Demo)#4 (1) { [“string”]=> string(4) “Siri” } object(Libs\Demo)#5 (1) { [“string”]=> string(4) “Siri” } object(Libs\Demo)#4 (1) { [“string”]=> string(4) “Demo” } object(Libs\Demo)#5 (1) { [“string”]=> string(4) “Siri” }
代码中提到了深拷贝和浅拷贝,那么我们先来分析一下这两者的区别
浅拷贝:被拷贝对象的所有变量都含有与原对象相同的值,而且对其他对象的引用仍然是指向原来的对象,即浅拷贝只负责当前对象实例,对引用的对象不做拷贝。
深拷贝:被拷贝对象的所有的变量都含有与原来对象相同的值,除了那些引用其他对象的变量,那些引用其他对象的变量将指向一个被拷贝的新对象,而不再是原来那些被引用的对象。即深拷贝把要拷贝的对象所引用的对象也拷贝了一次。而这种对被引用到的对象拷贝叫做间接拷贝。
在决定以深拷贝的方式拷贝一个对象的时候,必须决定对间接拷贝的对象时采取浅拷贝还是深拷贝还是继续采用深拷贝。
即深拷贝把要拷贝的对象所引用的对象也都拷贝了一次,而这种对被引用到的对象拷贝叫做间接拷贝。深拷贝要深入到多少层,是一个不确定的问题。
因此,在采取深拷贝时,需要决定多深才算深。此外,在深拷贝的过程中,很可能会出现循环引用的问题。
序列化深拷贝:利用序列化来做深拷贝,把对象写到流里的过程是序列化的过程,这一过程称为“冷冻”或“腌咸菜”,反序列化对象的过程叫做“解冻”或“回鲜”。
说一下浅拷贝和深拷贝
大学学习c语言时,提到过这两个的区别。我依稀记得是 值拷贝是深拷贝,而指针拷贝是浅拷贝。
浅复制呢又称为浅拷贝,深复制又称为深拷贝。
浅复制的话,就是通过一个原型实例(这里暂称为老对象)克隆所得到的对象(这里暂时称为新对象),
而这个新对象中所有的值类型变量都含有与老对象相同的值,
但是,新对象所有的对其他对象的引用却是和老对象指向同一个地方,
即对引用类型来说,老对象和新对象指向同一个引用对象。
深复制呢,和浅复制就一点不同,那就是,
新对象所有的对其他对象的引用都是指向了复制过的对象,而不再是和老对象指向同一个对象。
引用与推荐: