Prototype设计模式

在软件开 发中,有时候可能会需要创建一些特别复杂的对象,如果系统中已经存在同样类型的对象,并且不同的属性个数相差不大的话,用Prototype模式可能是一 个理想的选择。

定义  :用原型 实例指定创建物件的种类,并且通过拷贝这些原型创建新的物件。

Prototype 模式允许一个物件再创建另外一个可定制的物件,根本无需知道任何如何创建的细节,工作原理是:通过将一个原型物件传给那个要发动创建的物件,这个要发动创 建的物件通过请求原型物件拷贝它们自己来实施创建。

类图如下:

Prototype


从图上可以看出,使用方法很简单,只要调用 对象的clone方法返回一个新的对象就可以了。但是为什么没有其他新的方法来实现这个模式呢?因为Java中的Object提供了clone()方法来 实现对象的克隆,所以Prototype模式实现一下子变得很简单.

在这个clone方法中,我们只要调用Object 的克隆方法返回一个对象,就可以以最简单的方式实现Prototype模式。

在其他编程语言中,就需要创建一个当前类的新的对 象,然后把当前对象本身的各属性的值复制一份给新创建的对象,并且返回新对象即可。


从上图中的main函数的调用过程来看,也 可以很清晰地看出Prototype模式和其他创建型模式的不同:Prototype模式创建对象不是通过new一个类,而是通过一个现有的对象实例来 的。

什么时候应该使用prototype模式呢?  
1.当你要创建的对象与现有运行时对象相 似度很大时
2.为了避免创建类的工厂类导致层次复杂度增加时
3.当类的实例只有不多的几种状态时(此时需要引进原型管理器)

Prototype 模式常用在一些对象管理器中。这些对象管理器本身一般为单例模式,主要负责对象的创建和返回。由于返回的对象的类型基本上是一致的,而且返回的对象的各项 属性大多保持一致,只有极少数属性才需要修改,所以用Prototype无疑是极好的选择。

需要注意的是:浅拷贝和深拷 贝的区别。

简单的讲,浅拷贝就是只对当前对象的直属属性进行复 制,如果其属性是基本类型的话,就复制原对象的值;如果其属性是其他对象的话,就复制对象的地址。而深拷贝则是麻烦的多,如果其属性是对象的话,就需要创 建一个新的子属性的对象,并且对这个对象的各项属性进行复制,如果子属性还有子属性的话,则需要递归的进行复制操作。

一切就看需求,如果那些属性的值不会被变更的话,那 么只需要实现浅拷贝即可;否则,深拷贝就是必须的。

ProtoType uml


Java代码
  1. package  com.kingswood.pattern.creational.protoType;    
  2.     
  3. public   interface  ProtoType  extends  Cloneable {    
  4.     
  5.     public  Object clone();    
  6.     
  7. }    
package com.kingswood.pattern.creational.protoType;  
  
public interface ProtoType extends Cloneable {  
  
    public Object clone();  
  
}  
 

Java代码
  1. package  com.kingswood.pattern.creational.protoType;    
  2.     
  3. public   class  ConcreteProtoType  implements  ProtoType {    
  4.     
  5.     private  String propA;    
  6.     
  7.     private  String propB;    
  8.     
  9.     public  String getPropA() {    
  10.         return  propA;    
  11.     }    
  12.     
  13.     public   void  setPropA(String propA) {    
  14.         this .propA = propA;    
  15.     }    
  16.     
  17.     public  String getPropB() {    
  18.         return  propB;    
  19.     }    
  20.     
  21.     public   void  setPropB(String propB) {    
  22.         this .propB = propB;    
  23.     }    
  24.     
  25.     public  Object clone(){    
  26.         try  {    
  27.             return   super .clone();    
  28.         } catch  (CloneNotSupportedException e) {    
  29.             return   null ;    
  30.         }    
  31.     }    
  32.     
  33. }   
package com.kingswood.pattern.creational.protoType;  
  
public class ConcreteProtoType implements ProtoType {  
  
    private String propA;  
  
    private String propB;  
  
    public String getPropA() {  
        return propA;  
    }  
  
    public void setPropA(String propA) {  
        this.propA = propA;  
    }  
  
    public String getPropB() {  
        return propB;  
    }  
  
    public void setPropB(String propB) {  
        this.propB = propB;  
    }  
  
    public Object clone(){  
        try {  
            return super.clone();  
        } catch (CloneNotSupportedException e) {  
            return null;  
        }  
    }  
  
} 
 

Java代码
  1. package  com.kingswood.pattern.creational.protoType;    
  2.     
  3. import  junit.framework.TestCase;    
  4.     
  5. public   class  Client  extends  TestCase {    
  6.     
  7.     public   static   void  testMethod(){    
  8.     
  9.         ConcreteProtoType proto = new  ConcreteProtoType();    
  10.     
  11.         proto.setPropA("propA" );    
  12.     
  13.         proto.setPropB("propB" );    
  14.     
  15.         ConcreteProtoType newProto = (ConcreteProtoType) proto.clone();    
  16.     
  17.         assertNotSame(proto, newProto);    
  18.     
  19.         assertEquals(proto.getPropA(), newProto.getPropA());    
  20.     
  21.         assertEquals(proto.getPropB(), newProto.getPropB());    
  22.     
  23.     }    
  24. }    
package com.kingswood.pattern.creational.protoType;  
  
import junit.framework.TestCase;  
  
public class Client extends TestCase {  
  
    public static void testMethod(){  
  
        ConcreteProtoType proto = new ConcreteProtoType();  
  
        proto.setPropA("propA");  
  
        proto.setPropB("propB");  
  
        ConcreteProtoType newProto = (ConcreteProtoType) proto.clone();  
  
        assertNotSame(proto, newProto);  
  
        assertEquals(proto.getPropA(), newProto.getPropA());  
  
        assertEquals(proto.getPropB(), newProto.getPropB());  
  
    }  
}  
 
以上样例使用浅克隆方式实现proto type模式,浅克隆无法对对象中包含的其他非java原是类型数据进行复制。如果需要复制其他非java原是类型数据,则需要使用深克隆方式,对象以及 其内部所有对象必须实现java.io.Serializable接口,clone方法改写成以下形式:


Java代码
  1. public  Object clone(){    
  2.     
  3.         try  {    
  4.     
  5.             ByteArrayOutputStream ot = new  ByteArrayOutputStream();    
  6.     
  7.             ObjectOutputStream oo = new  ObjectOutputStream(ot);    
  8.     
  9.             oo.writeObject(this );    
  10.     
  11.             ByteArrayInputStream it = new  ByteArrayInputStream(ot.toByteArray());    
  12.     
  13.             ObjectInputStream oi = new  ObjectInputStream(it);    
  14.     
  15.             return  (oi.readObject());    
  16.     
  17.         } catch  (IOException e) {    
  18.             e.printStackTrace();    
  19.             return   null ;    
  20.         } catch  (ClassNotFoundException e) {    
  21.             e.printStackTrace();    
  22.             return   null ;    
  23.         }    
  24.     
  25.     }   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值