定义
Specify the kinds of objects to create using a prototypical instance, and create new objects by copying this prototype.
用原型实例指定要创建对象的种类,并通过拷贝这些原型创建新的对象。
使用场景
看如下类图:
这是抽象工厂模式的类图, 如果我们需要某一个特定的地形(terrain),就需要使用相对应的地形工厂类来创建对象。这样的搭配有时候显得不那么灵活。当我们不想要平行的继承体系,而需要最大化的运行时的灵活性时,我们就可以使用抽象工厂模式的变形——原型模式。
代码
Forest.php 文件内容如下
<?php
namespace Prototype;
class Forest {}
class EarthForest extends Forest {}
class MarsForest extends Forest {}
Plains.php 文件内容如下
<?php
namespace Prototype;
class Plains {}
class EarthPlains extends Plains {}
class MarsPlains extends Plains {}
Sea.php 文件内容如下
<?php
namespace Prototype;
class Sea {}
class EarthSea extends Sea {}
class MarsSea extends Sea {}
TerrainFactory.php 文件内容如下
<?php
namespace Prototype;
class TerrainFactory
{
private $sea;
private $plains;
private $forest;
public function __construct (Sea $sea ,Plains $plains ,Forest $forest) {
$this->sea = $sea;
$this->plains = $plains;
$this->forest = $forest;
}
public function getSea() {
return clone $this->sea;
}
public function getPlains() {
return clone $this->plains;
}
public function getForest() {
return clone $this->forest;
}
}
说明
这样我们就可以生成需要的地形
<?php
require '../public.php';
require_once 'Sea.php';
require_once 'Plains.php';
require_once 'Forest.php';
use \Prototype\TerrainFactory;
use \Prototype\Sea;
use \Prototype\EarthSea;
use \Prototype\Plains;
use \Prototype\EarthPlains;
use \Prototype\Forest;
use \Prototype\EarthForest;
$terrian = new TerrainFactory(new EarthSea ,new EarthPlains ,new EarthForest);
通过关键字 clone(克隆)就可以实现对象的拷贝。值得注意的是如果被拷贝的对象中有属性,且该属性也是一个object,那么拷贝之后的新对象的属性里面保存的并不是一个新对象,还是原来对象的一个引用。也就是说这里完成的是浅复制,如果要得到的新对象里面的属性也是一个全新的对象,则要实现深复制。即通过实现__clone()方法。