介绍
原型模式用来创建重复的对象,减少对象创建初始化的性能开销,属于创建型模式。
处理文件实例
模拟一个需求,文件类要处理 Word 和 Excel 两种文件类型,先定义了一个文件抽象类,再由具体的 Word 类和 Excel 类去实现,抽象类中定义了 clone 方法,会在具体的子类实现时初始化文件类型属性type,由产品类将这两个文件类封装在属性中,在根据业务需求调用不同对象的同时执行 clone 操作,复制新对象。
<?php
abstract class FilePrototype
{
public $type;
public function read()
{
echo "read $this->type file";
}
public function write()
{
echo "write $this->type file";
}
abstract public function getType();
abstract public function setType($type);
public function __clone()
{
$this->type = '';
}
}
class WordFile extends FilePrototype
{
public function __construct()
{
$this->type = 'word';
}
public function getType()
{
return $this->type;
}
public function setType($type)
{
$this->type = $type;
}
}
class ExcelFile extends FilePrototype
{
public function __construct()
{
$this->type = 'word';
}
public function getType()
{
return $this->type;
}
public function setType($type)
{
$this->type = $type;
}
}
class ProductPrototype
{
public $map = [];
/**
* @param $id string 对象名称
*/
public function getMap($id)
{
if($this->map){
return clone $this->map[$id];
}
return false;
}
/**
* 对象存储入数组
* @param $objectName string 目标对象
*/
public function setMap($objectName)
{
if($objectName){
$this->map[$objectName] = new $objectName;
}
return false;
}
public function coll()
{
$this->setMap('WordFile');
$this->setMap('ExcelFile');
}
}
$productPrototype = new ProductPrototype();
$productPrototype->coll();
$wordFile = $productPrototype->getMap('WordFile');
$wordFile->setType('text'); #对象复制后,可对属性进行重新赋值,改变对象
$wordFile->read(); #read text file
$wordFile->write(); #write text file
$excelFile = $productPrototype->getMap('ExcelFile');
$excelFile ->setType('xlsx'); #对象复制后,可对属性进行重新赋值,改变对象
$excelFile->read(); #read xlsx file
$excelFile->write(); #write xlsx file
总结
原型模式是创建对象的一种模式,对象的创建过程,在实际的工作中往往是复杂的,一个构造函数会同时去做权限的判断,属性的赋值,配置文件的读取,是个消耗资源很多的过程,而内存的复制往往是快速高效的,并且在一个生命周期中一个对象往往会多次用到,仅仅只是修改了个别属性,却要去重新创建对象,这样是划不来的,通过原型模式获取克隆后的对象后,像例子中的修改type属性,就可以改变输出。但原型模式在创建克隆对象时往往要考虑类的整体功能,对新建立的类不会麻烦,对于过去存在的类,改动是比较困难的。