原型模式属于对象的创建模式--通过给出一个原型对象来指明所要创建的对象的类型。然后用复制这个原型对象的方法创建出更多同类型的对象。
一般涉及三个角色
客户角色:客户提出创建对象的请求。
抽象原型角色:这是一个抽象角色,通常由一个接口类或抽象类实现,此角色给出所有的具体原型类所需的接口。
具体原型角色,被复制的对象,此角色需要实现抽象的原型角色所要求的接口。
深拷贝模式:深copy通过序列化和反序列化完成copy,新copy的内容完全复制原来的内容。原来的内容变化,新内容不变。
1 /** 2 *原型模式 3 * 4 */ 5 6 /** 7 * 抽象原型模式 8 */ 9 interface Prototype{ 10 11 public function copy(); 12 13 } 14 15 class ConcretePrototype implements Prototype{ 16 17 private $name; 18 19 public function __construct($name){ 20 21 $this->name=$name; 22 } 23 24 public function setName($name){ 25 26 $this->name=$name; 27 } 28 29 public function getName(){ 30 31 return $this->name; 32 33 34 } 35 36 public function copy(){ 37 38 /** 39 * 深copy 40 */ 41 $serialize_obj=serialize($this); 42 $clone_obj=unserialize($serialize_obj); 43 return $clone_obj; 44 45 } 46 47 } 48 49 /** 50 * 测试深拷贝 51 */ 52 53 class DeepCopyDemo{ 54 55 public $array; 56 } 57 58 class Client{ 59 60 /** 61 * main program 62 */ 63 public static function main(){ 64 65 $demo=new DeepCopyDemo(); 66 67 $demo->array=array(1,2); 68 69 $object1=new ConcretePrototype($demo); 70 71 $object2=$object1->copy(); 72 73 var_dump($object1->getName()); 74 echo '<br/>'; 75 var_dump($object2->getName()); 76 echo '<br/>'; 77 78 $demo->array = array(3, 4); 79 var_dump($object1->getName()); 80 echo '<br />'; 81 var_dump($object2->getName()); 82 echo '<br />'; 83 } 84 85 } 86 87 Client::main();
浅copy模式:直接copy,拷贝了源对象的引用地址等,所以原来内容变化,新内容变化。
1 /** 2 *原型模式 3 * 4 */ 5 6 /** 7 * 抽象原型模式 8 */ 9 interface Prototype{ 10 11 public function copy(); 12 13 } 14 15 class ConcretePrototype implements Prototype{ 16 17 private $name; 18 19 public function __construct($name){ 20 21 $this->name=$name; 22 } 23 24 public function setName($name){ 25 26 $this->name=$name; 27 } 28 29 public function getName(){ 30 31 return $this->name; 32 33 34 } 35 36 public function copy(){ 37 38 // /** 39 // * 深copy 40 // */ 41 // $serialize_obj=serialize($this); 42 // $clone_obj=unserialize($serialize_obj); 43 // return $clone_obj; 44 45 return clone $this;//浅拷贝 46 47 } 48 49 } 50 51 /** 52 * 测试深拷贝 53 */ 54 55 class DeepCopyDemo{ 56 57 public $array; 58 } 59 60 class Client{ 61 62 /** 63 * main program 64 */ 65 public static function main(){ 66 67 $demo=new DeepCopyDemo(); 68 69 $demo->array=array(1,2); 70 71 $object1=new ConcretePrototype($demo); 72 73 $object2=$object1->copy(); 74 75 var_dump($object1->getName()); 76 echo '<br/>'; 77 var_dump($object2->getName()); 78 echo '<br/>'; 79 80 $demo->array = array(3, 4); 81 var_dump($object1->getName()); 82 echo '<br />'; 83 var_dump($object2->getName()); 84 echo '<br />'; 85 } 86 87 } 88 89 Client::main();
在什么情况下使用原始模型模式:
假设一个系统产品类是动态加载的,而且产品类具有一定的等级结构,这个时候如果采取工厂模式的话,工厂类就不得不具有一个相应的等级结构,而产品类的等级结构一旦变化,工厂类的等级结构就不得不随之变化,这对于产品结构可能会有经常变化的系统来说,采用工厂模式就有不方便之处。
这时候如果采取原始模型模式给每一个产品类配备一个克隆方法,便可避免使用工厂模式所带来的具有固定等级结构的工厂类。