<?php
/**
* 设计模式 一 原型模式 Prototype
*/
/**
* 定义:用原型实例指定创建对象的种类,并且通过拷贝这些原型达到创建新的对象目的。
* Prototype原型模式是一种创建型设计模式,Prototype模式允许一个对象再创建另一个可制定的对象,
* 根本无需知道任何创建的细节。
*
* 工作原理:通过一个原型对象传给 那个要发动创建的对象,这个要发动创建的对象是通过请求原型对象克隆原型对象自身。
*
*/
/**
* 优点:
* 1、可以在运行时刻添加和删除产品
* 2、可以改变值以指定新对象。
* 3、可以改变结构以指定新对象。
* 4、减少子类构造。
* 5、用类动态配置应用。
*
* 缺点:
* 1、prototype模式的最主要缺点就是每个类必须配备一个克隆方法。
* 而且这个克隆方法需要对类的功能进行通盘考虑,这对全新的类来说不是很难,但对已有的类进行改造时,不一定是件容易的事。
*
*/
/**
* 适用场景
* 1、当一个系统应该独立于它的产品创建、构成和表示时,要使用Prototype
* 2、当要实例化的类是在运行时刻指定时,例如动态加载。
* 简历,星际小怪。
*/
/**
* 抽象原型。
*/
abstract class Prototype {
public abstract function clone();
}
class ConcreteAPrototype extends Prototype {
public $name;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
public function clone() {
return clone $this;
}
}
$p1 = new ConcreteAPrototype('lmq');
$p2 = $p1->clone();
var_export($p1);
$p2->name = 'lmq2';
var_export($p2);
/**
* 继续发展,由于原型对象比较多,需要一个原型管理类,
*/
class PrototypeManager {
private $_prototypeList = array();
//增加原型,第一个参数为原型的名字,第二个参数为原型对象
public function addPrototype($name, $prototype) {
$this->_prototypeList[$name] = $prototype;
}
public function getPrototype($name) {
return $this->_prototypeList[$name];
}
public function removePrototype($name) {
return unset($this->_prototypeList[$name]);
}
//获取原型的克隆,也就是替代new的方法,参数为原型的名字
public function getClone($name) {
return clone $this->_prototypeList[$name];
}
}
//初始化管理类
$manager = new PrototypeManager();
//初始化两个属于不同的原型
$prototypeA = new ConcreteAPrototype('lmq');
$prototypeB = new ConcreteAPrototype('lmq2');
//增加原型,同时用比较容易记忆的名字来命名原型
$manager->addPrototype('p1', $prototypeA);
$manager->addPrototype('p2', $prototypeB);
//当需要新增对象的时候,我们可以不必知道对象的类名和初始化的工作
$objcetA = $manager->getClone('p1');
/*
我们一般用new来新增对象,不过很多时候新增一个对象需要一些工作。而星际里面往往会新增某些类的大量的对象,比如新增很多机枪兵和龙骑。
待解决的问题:我们能否减少new的使用,同时避免需要新增对象的时候,了解对象的类名。
思路:php5提供了克隆方法,我们可以新增一个对象,然后每次需要新增和她同类的对象,克隆他就可以了。
原型(Prototype)模式示例:
*/
//机枪兵类
class Marine {
//所属的用户ID
public $playerID
//构造函数,参数为用户的id
public function __construct($id) {
$this->playerID = $id;
}
}
//兵种的管理类
class TroopManager {
//数组,用于存放多个兵种的原型
public $troopPrototype = array();
//增加原型,第一个参数为原型的名字,第二个参数为原型对象
public function addPrototype($name, $prototype) {
$this->troopPrototype[$name] = $prototype;
}
//获取原型的克隆,也就是替代new的方法,参数为原型的名字
public function getPrototype($name) {
return clone $this->troopPrototype[$name];
}
}
//初始化兵种的管理类
$manager = new TroopManager();
//初始化两个属于不同玩家的机枪兵的原型
$m1 = new Marine(1);
$m2 = new Marine(2);
//增加原型,同时用比较容易记忆的名字来命名原型
$manager->addPrototype('Marine of 1', $m1);
$manager->addPrototype('Marine of 2', $m2);
//当需要新增对象的时候,我们可以不必知道对象的类名和初始化的工作
$m3 = $manager->getPrototype('Marine of 1');
/*
用途总结:原型模式可以将新增对象的工作细节封装。
实现总结:需要一个原型管理类,实现增加和获取克隆原型的方法。注意这里由于为了简明,省略了一些东西,实际上我们可以在克隆方法上做一些改动,也可以用接口规范每个原型类。
*/