原型模式:
通过clone原型创建新的对象,不需要知道任何创建的细节。
思维导图:
抽象原型(Prototype)角色:声明一个克隆自身的接口。
具体原型(Concrete Prototype)角色:实现一个克隆自身的操作。
代码:
<?php
/**
* 原型模式
*/
/*
*抽象原型角色
*/
interface Prototype {
public function copy();
}
/*
*具体原型角色
*/
class ConcretePrototype implements Prototype {
private $_property;
private $_obj = new OtherClass(); //一个其他类的实例
private $_arr = [1,2,3];
function __construct($property){
$this->_property = $property;
}
function getPro(){
return $this->_property;
}
function clone(){
return clone $this;
}
/*
*注意:如果当前类中属性有其他类的实例的话,clone $this时新属性还是指向
*原来的类,即默认为浅复制,通过__clone来进行深复制
*php中引用赋值类型(array,object)等都需要进行深复制操作
*/
function __clone(){
$this->_obj = clone $this_obj;
$this->_arr = clone $this->_arr;
}
}
//客户端
class Client {
public static function main(){
$p = new ConcretePrototype('prototype');
$newP = $pro->clone();
echo $p->getPro();
echo $newP->getPro();
}
}
Client::main();
优缺点:
可以在运行时刻增加和删除产品
可以改变值以指定新对象
可以改变结构以指定新对象
减少子类的构造
用类动态配置应用
Prototype模式的最主要缺点就是每一个类必须配备一个克隆方法。
且这个克隆方法需要对类的功能进行通盘考虑,这对全新的类来说不是很难,但对已有的类进行改造时,不一定是件容易的事。
使用场景:
当一个系统应该独立于它的产品创建、构成和表示时,要使用Prototype模式
当要实例化的类是在运行时刻指定时,例如动态加载
为了避免创建一个与产品类层次平等的工厂类层次时
当一个类的实例只能有几个不同状态组合中的一种时。建立相应数目的原型并克隆它们可能比每次用合适的状态手工实例化该类更方便一些