原型模式
原型模式(Prototype Pattern)是先创建好一个原型对象,然后通过clone原型对象来创建新的对象。适用于大对象的创建,因为创建一个大对象需要很大的开销,如果每次new就会消耗很大,原型模式仅需内存拷贝即可。
Ø 优点
1. 性能优良。原型模式是在内存二进制流的拷贝,要比直接new一个对象性能好很多,特别是要在一个循环体内产生大量的对象时,原型模式可以更好地体现其优点。
2. 逃避构造函数的约束。这个既是优点也是缺点。
Ø 缺点
1、配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类不是很难,但对于已有的类不一定很容易,特别当一个类引用不支持串行化的间接对象,或者引用含有循环结构的时候。
2、必须实现 Cloneable 接口。
Ø 主要解决
在运行期建立和删除原型。
Ø 何时使用
1、当一个系统应该独立于它的产品创建,构成和表示时。
2、当要实例化的类是在运行时刻指定时,例如,通过动态装载。
3、为了避免创建一个与产品类层次平行的工厂类层次时。
4、当一个类的实例只能有几个不同状态组合中的一种时。建立相应数目的原型并克隆它们可能比每次用合适的状态手工实例化该类更方便一些。
Ø 应用场景
1.资源优化场景。类初始化需要消耗非常多的资源,这个资源包括数据、硬件资源等。
2.性能和安全要求的场景。通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。
3.一个对象多个修改者的场景。一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用。
Ø 实现
原型接口类:Prototype.php
interface Prototype{
public function copy();
public function deepCopy();
}
ConcretePrototype.php
class ConcretePrototype implements Prototype{
private $_name;
public function __construct($name)
{
$this->_name = $name;
}
/**
* 浅拷贝
*/
public function copy(){
return clone $this;
}
/**
* 深拷贝
*/
public function deepCopy(){
return unserialize(serialize($this));
}
public function getName(){
return $this-> _name;
}
public function setName($name){
$this->_name = $name;
}
}
UsePrototype.php
class Demo
{
public $string;
}
class UsePrototype
{
public function copy()
{
$demo = new Demo();
$demo->string = "copyA";
$object_first = new ConcretePrototype($demo);
$object_second = $object_first->copy();
var_dump($object_first->getName());
echo '<br/>';
var_dump($object_second->getName());
echo '<br/>';
$demo->string = "copyB";
var_dump($object_first->getName());
echo '<br/>';
var_dump($object_second->getName());
echo '<br/>';
}
public function deepCopy()
{
$demo = new Demo();
$demo->string = "deepCopyA";
$object_first = new ConcretePrototype($demo);
$object_second = $object_first->deepCopy();
var_dump($object_first->getName());
echo '<br/>';
var_dump($object_second->getName());
echo '<br/>';
$demo->string = "deepCopyB";
var_dump($object_first->getName());
echo '<br/>';
var_dump($object_second->getName());
echo '<br/>';
}
}
测试调用
$up = new App\Prototype\UsePrototype;
$up->copy();
echo '<hr>';
$up->deepCopy();
结果:
object(App\Prototype\Demo)#2 (1) { ["string"]=> string(5) "copyA" }
object(App\Prototype\Demo)#2 (1) { ["string"]=> string(5) "copyA" }
object(App\Prototype\Demo)#2 (1) { ["string"]=> string(5) "copyB" }
object(App\Prototype\Demo)#2 (1) { ["string"]=> string(5) "copyB" }
-------------------------------------------------------------------------
object(App\Prototype\Demo)#4 (1) { ["string"]=> string(9) "deepCopyA" }
object(App\Prototype\Demo)#5 (1) { ["string"]=> string(9) "deepCopyA" }
object(App\Prototype\Demo)#4 (1) { ["string"]=> string(9) "deepCopyB" }
object(App\Prototype\Demo)#5 (1) { ["string"]=> string(9) "deepCopyA" }
浅拷贝:(clone) 被拷贝对象的所有变量都含有与原对象相同的值,而且对其他对象的引用仍然是指向原来的对象,即浅拷贝只负责当前对象实例,对引用的对象不做拷贝。
深拷贝:把要拷贝的对象所引用的对象也拷贝了一次。