创建对象_原型(Prototype)模式_深拷贝
顾客:“给我几个快递。”快递员:“寄往什么地方?寄给...?”顾客:“和上次差不多一样,只是邮寄给另外一个地址,这里是邮寄地址...“把邮寄地址的纸条给快递员。快递员:“好。”
- 要实现克隆,必须实现 java.lang.Cloneable 接口,否则在运行时调用 clone( ) 方法,会抛出 CloneNotSupportedException异常。
- 返回的是 Object类型的对象,所以使用时可能需要强制类型转换。
- 该方法是 protected的,如果想让外部对象使用它,必须在子类重写该方法,设定其访问范围是 public的,参见 PackageInfo 的 clone( ) 方法。
- Object 的 clone( ) 方法的复制是采用逐字节的方式从内存赋值数据,复制了属性了引用,而属性所指向的对象本身没有被复制,因此所复制的引用指向了相同的对象。即 浅拷贝。
public   class  PackageInfo  implements  Cloneable {
     public   PackageInfo  clone() {
         try  {
             return  (PackageInfo)  super .clone();
        }  catch  (CloneNotSupportedException e) {
            System. out .println( "Cloning not allowed." );
             return   null ;
        }
    }
     // 静态工厂方法:根据原型创建一份副本
     public   static  PackageInfo clonePackage(String userName) {
         // 根据 userName加载一条用户以前的数据作为原型数据(数据库或其它保存的数据)
        PackageInfo prototype =  loadPackageInfo (userName);
         // 再在内存中克隆这条数据
        prototype =  prototypr .clone();
         // 初始化数据 id(主键)
        prototype. setId ( null );
         // 返回数据
         return  prototype;
    }
}
- 复制对象时,递归地调用属性对象的克隆方法。根据具体的类,撰写出实现特定类型的深拷贝方法。
一般我们很难实现一个一般性的方法来完成任何类型对象的深拷贝。根据反射得到属性的类型,然后依照它的类型构造对象,但前提是:这些属性的类型必须含有一个公有的默认构造方法,否则作为一个一般性的方法,很难确定传递给非默认构造方法的参数值;此外,如果属性类型是接口或者抽象类型,必须提供查找到相关的具体类方法,作为一个一般性的方法,这个也很难办到。
- 如果类实现了 java.io.Serializable 接口,把原型对象序列化,然后反序列化后得到得对象,其实就是一个新的深拷贝对象。
//DeepCopyBean实现了 java.io.Serializable接口
public class DeepCopyBean implements Serializable {
// 原始类型属性
private int primitiveField ;
// 对象属性
private String objectField ;
// 首先序列化自己到流中,然后从流中反序列化,得到得对象便是一个新的深拷贝
public DeepCopyBean deepCopy() {
try {
ByteArrayOutputStream buf = new ByteArrayOutputStream();
ObjectOutputStream o = new ObjectOutputStream(buf);
o.writeObject( this );
ObjectInputStream in = new ObjectInputStream(
new ByteArrayInputStream(buf.toByteArray()));
return (DeepCopyBean) in.readObject();
} catch (Exception e) {
e.printStackTrace();
}
return null ;
}
// 属性 get、set 方法略... // 测试demo
public static void main(String[] args) {
DeepCopyBean originalBean = new DeepCopyBean();
// 创建两个 String对象,其中一个在 JVM的字符串池(String pool)里,属性引用指向另外一个在堆里的对象
originalBean.setObjectField( new String( "guilin" ));
originalBean.setPrimitiveField(50);
// 深拷贝
DeepCopyBean newBean = originalBean.deepCopy();
// 原始类型属性值比较:true
System. out .println( "primitiveField ==:"
+ (originalBean.getPrimitiveField() == newBean
.getPrimitiveField()));
// 对象属性值比较:false(证明未指向相同的地址)
System. out .println( "objectField ==:"
+ (originalBean.getObjectField() == newBean.getObjectField()));
// 对象属性 equals 比较:true
System. out .println( "objectField equal:"
+ (originalBean.getObjectField().equals(newBean
.getObjectField())));
}
}
- 它只能复制实现 Serializable接口类型的对象,其属性也是可序列化的;
- 序列化和反序列化比较耗时。
- 创建大的聚合对象图时,没有必要为每个层次的子对象创建相应层次的工厂类。
- 方便实例化,只要复制对象,然后初始化对象,就可以得到想要的对象。
创建对象_原型(Prototype)模式_深拷贝的更多相关文章
- 桥接模式_NAT模式_仅主机模式_模型图.ziw
		2017年1月12日, 星期四 桥接模式_NAT模式_仅主机模式_模型图 null 
- 原型(Prototype)模式
		原型模式属于对象的创建模式.通过给出一个原型对象来指明所有创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象.这就是原型模式的用意.原型模式的结构 原型模式要求对象实现一个可以“克隆 ... 
- Java 实现原型(Prototype)模式
		public class BaseSpoon implements Cloneable {//spoon 匙, 调羹 String name; public String getName() { re ... 
- 设计模式C++描述----08.原型(Prototype)模式
		一. 概述 定义:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 换句话说,就是不用重新初始化对象,而是动态地获得对象运行时的状态. 再说明白点,就是要一个拷贝过构造函数类似功能的接 ... 
- 设计模式--原型(Prototype)模式
		写这些也许有人认为“为了模式而模式”.Insus.NET所想到的,每个大师成为大师之前,也许都得这样做. 走路,从小就开始学,直至现在,谁还不是为了走路而走路?一直重复着...... 很多人没有分享自 ... 
- 六、原型(Prototype)模式
		原型模式是对象的创建模式,通过给出一个原型对象来指明所要创建的对象的类型.然后用复制这个原型对象的方法来创建出更多同类型的对象. 原型模式可以不用重新初始化对象,而动态的获取对象运行时的状态.使用原型 ... 
- 分组密码_计数器(CTR)模式_原理及java实现
		一.原理: CTR模式是一种通过将逐次累加的计数器进行加密来生成密钥流的流密码,在CTR模式中,每个分组对应一个逐次累加的计数器,并通过对计数器进行加密来生成密钥流.最终的密文分组是通过将计数器加密得 ... 
- Java设计模式_创建型模式_单例模式
		单例模式的实现: 定义一个类,在类中定义该类的静态变量,再定一个一个获取该类的静态变量的方法. UML图: 
- 克隆复制可使用原型( Prototype)设计模式
		今天有学习设计模式的原型(Prototype)<设计模式--原型(Prototype)模式>http://www.cnblogs.com/insus/p/4152773.html .为了加 ... 
- C#设计模式:原型模式(Prototype)及深拷贝、浅拷贝
		原型模式(Prototype) 定义: 原型模式:用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象.被复制的实例被称为原型,这个原型是可定制的. Prototype Pattern也是一 ... 
随机推荐
- ESB后台error日志
			本地tomcat没异常 开发环境,生产环境 ESB使用axis2.jar 后台会有错误,但不影响所有流程,该错误源自common.log的error,在捕捉异常后,并未往外继续抛 [ESB 打印] 接 ... 
- HDU 5778 abs (素数,暴力)
			题意:给定一个数x,求正整数y≥2y\geq 2y≥2,使得满足以下条件: 1.y-x的绝对值最小 2.y的质因数分解式中每个质因数均恰好出现2次. 析:由于y质因数分解式中每个质因数均出现2次,那么 ... 
- HDU 5777 domino (排序,水题)
			题意:小白在玩一个游戏.桌子上有n张多米诺骨牌排成一列.它有k次机会,每次可以选一个还没有倒的骨牌,向左或者向右推倒.每个骨 牌倒下的时候,若碰到了未倒下的 骨牌,可以把它推倒.小白现在可以随意设置骨 ... 
- HeapAlloc、GlobalAlloc和new等内存分配有什么区别么?
			查找了一些 new , GlobalAlloc, HeapAlloc分配内存方式的区别. 转了一些资料 //============================================== ... 
- Custom ReadOnlyProperty【PluraSight】
			Limited functionality: Not settable No data binding No validation No animation No Inheritance When t ... 
- android 解释dp,px,pt,sp单位
			1.dp(dip):不同设备有不同的显示效果,这个和设备硬件有关系,一般我们为了支持WVGA,HVGA和QVGA对剑使用这个,它是不依赖像素的 2.px:pixels(像素),不同设备显示效果相同,一 ... 
- UI:关于RGB与16进制颜色值的转换
			IOS基本图形绘制 参考 取色对照表 参照 页面背景改为 #5CACEE 的颜色.有两个方法 方法一: 加两个宏 #define UIColorFromHexWithAlpha(hexValu ... 
- ActiveMQ的消息确认问题
			http://riddickbryant.iteye.com/blog/441890 [发送端] session = connection.createSession(Boolean.FALSE, ... 
- 利用C#实现对excel的写操作
			一.COM interop 首先我们要了解下何为COM Interop,它是一种服务,可以使.NET Framework对象能够与COM对象通信.Visual Studio .NET 通过引入面向公共 ... 
- 【腾讯内部干货分享】分析Dalvik字节码进行减包优化
			http://wetest.qq.com/lab/view/?id=96?from=ads_test2_qqtips&sessionUserType=BFT.PARAMS.192184.TAS ... 
