原型模式属于创建模式的一种,其主要解决的是频繁重复创建同一对象时性能的开销的问题。其实现方式主要是在创建新对象时不是直接去实例化创建新的对象,而是通过复制(克隆)已存在对象(原型)的方式来实现。
从上边的介绍我们也可以很明确的得到原型模式的使用场景:当你的应用涉及到需要频繁的创建同一对象的多个实例时便可以考虑使用原型对象了。由于 php 原生的提供了 clone 关键字的实现,这是的你可以很轻松的创建一个对象的副本。
而提到原型模式就不得不提到两个概念 -- 浅拷贝,深拷贝(值拷贝是深拷贝,而指针拷贝是浅拷贝)。
所谓浅拷贝就是:就是通过一个原型实例对象克隆所得到的新对象对象,而且这个新对象中所有的值类型变量都含有与老对象相同,但是,新对象所有的对其他对象的引用却是和老对象指向同一个地方。
所谓的深拷贝就是:被拷贝对象拥有与原来对象相同的变量和值,除了那些引用其他对象的变量指向了拷贝的新对象,而不再是原来那些被引用的对象。即深拷贝把要拷贝的对象所引用的对象也拷贝了一次。而这种对被引用到的对象拷贝叫做间接拷贝。
在决定以深拷贝的方式拷贝一个对象的时候,必须决定对间接拷贝的对象时采取浅拷贝还是深拷贝还是继续采用深拷贝。
深拷贝的实现:序列化,利用序列化来做深拷贝,然后获取反序列化后的对象。
php
class Sea{}
class EarthSea extends Sea{}
class MarsSea extends Sea{}
class Plains{}
class EarthPlains extends Plains{}
class MarsPlains extends Plains{}
class Forest{}
class EarthForest extends Forest{}
class MarsForest extends Forest{}
class TerrainFactory
{
private $sea;
private $earth;
private $forest;
public function __construct(Sea $sea, Plains $earth, Forest $forest)
{
$this->sea = $sea;
$this->earth = $earth;
$this->forest = $forest;
}
//浅拷贝
public function getSea()
{
return clone $this->sea;
}
//浅拷贝
public function getEarth()
{
return clone $this->earth;
}
//深拷贝
public function getForest()
{
$temp = serialize($this->forest);
return unserialize($temp);
}
}
$factory = new TerrainFactory(new EarthSea(), new EarthPlains(), new EarthForest());
print_r($factory->getSea());
print_r($factory->getEarth());
print_r($factory->getForest());
需要注意的是克隆不会启动构造函数中的动作,但是可以使用构造函数生成的默认赋值。这大概也是原型模式能减少对象创建时开销的原因。