`

设计模式-原型模式(对象克隆)

阅读更多
原型模式-对象的克隆:
引用

浅克隆ShallowClone和深度克隆(DeepClone)
按照java数据类型: 基本类型(值类型)和引用类型(对象类型)
值类型包括int、double、byte、boolean、char等简单数据类型,引用类型包括类、接口、数组等复杂类型。
浅克隆值 基本类型能够进行复制,而对象引用复制的是指针。
在Java语言中,通过覆盖Object类的clone()方法可以实现浅克隆

浅克隆

//工作周报WeeklyLog
class WeeklyLog implements Cloneable
{
     //为了简化设计和实现,假设一份工作周报中只有一个附件对象,实际情况中可以包含多个附件,可以通过List等集合对象来实现
       private Attachment attachment;
private String name;
       private  String date;
       private  String content;
    public void setAttachment(Attachment  attachment) {
              this.attachment = attachment;
       }
       public  void setName(String name) {
              this.name  = name;
       }
       public  void setDate(String date) {
              this.date  = date;
       }
       public  void setContent(String content) {
              this.content  = content;
       }
public Attachment  getAttachment(){
              return (this.attachment);
       }
       public  String getName() {
              return  (this.name);
       }
       public  String getDate() {
              return  (this.date);
       }
       public  String getContent() {
              return  (this.content);
       }
     //使用clone()方法实现浅克隆
       public WeeklyLog clone()
       {
              Object obj = null;
              try
              {
                     obj = super.clone();
                     return (WeeklyLog)obj;
              }
              catch(CloneNotSupportedException  e)
              {
                     System.out.println("不支持复制!");
                     return null;
              }
       }
}

[b]客户端代码[/b]
class Client
{
       public  static void main(String args[])
       {
              WeeklyLog  log_previous, log_new;
              log_previous  = new WeeklyLog(); //创建原型对象
              Attachment  attachment = new Attachment(); //创建附件对象
              log_previous.setAttachment(attachment);  //将附件添加到周报中
              log_new  = log_previous.clone(); //调用克隆方法创建克隆对象
              //比较周报
              System.out.println("周报是否相同? " + (log_previous ==  log_new));
              //比较附件
              System.out.println("附件是否相同? " +  (log_previous.getAttachment() == log_new.getAttachment()));
       }
}
      编译并运行程序,输出结果如下:
周报是否相同?  false
附件是否相同? true



   由于使用的是浅克隆技术,因此工作周报对象复制成功,通过“==”比较原型对象和克隆对象的内存地址时输出false;但是比较附件对象的内存地址时输出true,说明它们在内存中是同一个对象。

2.深克隆
在深克隆中,无论原型对象的成员变量是值类型还是引用类型,都将复制一份给克隆对象,深克隆将原型对象的所有引用对象也复制一份给克隆对象。
   在Java语言中,如果需要实现深克隆,可以通过序列化(Serialization)等方式来实现。序列化就是将对象写到流的过程,写到流中的对象是原有对象的一个拷贝,而原对象仍然存在于内存中。通过序列化实现的拷贝不仅可以复制对象本身,而且可以复制其引用的成员对象,因此通过序列化将对象写到一个流中,再从流里将其读出来,可以实现深克隆。需要注意的是能够实现序列化的对象其类必须实现Serializable接口,否则无法实现序列化操作。
//附件类
class  Attachment implements Serializable
{
       private  String name; //附件名
       public  void setName(String name)
       {
              this.name  = name;
       }
       public  String getName()
       {
              return  this.name;
       }
     public void download()
     {
            System.out.println("下载附件,文件名为" + name);
     }
}
[b]   工作周报类WeeklyLog不再使用Java自带的克隆机制,而是通过序列化来从头实现对象的深克隆,我们需要重新编写clone()方法,修改后的代码如下:[/b]
//工作周报类
class  WeeklyLog implements Serializable
{
       private  Attachment attachment;
       private  String name;
       private  String date;
       private  String content;
       public  void setAttachment(Attachment attachment) {
              this.attachment  = attachment;
       }
       public  void setName(String name) {
              this.name  = name;
       }
       public  void setDate(String date) {
              this.date  = date;
       }
       public  void setContent(String content) {
              this.content  = content;
       }
       public  Attachment getAttachment(){
              return  (this.attachment);
       }
       public  String getName() {
              return  (this.name);
       }
       public  String getDate() {
              return  (this.date);
       }
       public  String getContent() {
              return  (this.content);
       }
   //使用序列化技术实现深克隆
       public WeeklyLog deepClone() throws  IOException, ClassNotFoundException, OptionalDataException
       {
              //将对象写入流中
              ByteArrayOutputStream bao=new  ByteArrayOutputStream();
              ObjectOutputStream oos=new  ObjectOutputStream(bao);
              oos.writeObject(this);
             
              //将对象从流中取出
              ByteArrayInputStream bis=new  ByteArrayInputStream(bao.toByteArray());
              ObjectInputStream ois=new  ObjectInputStream(bis);
              return  (WeeklyLog)ois.readObject();
       }
}
[b]深度克隆-客户端[/b]
class Client
{
       public  static void main(String args[])
       {
              WeeklyLog  log_previous, log_new = null;
              log_previous  = new WeeklyLog(); //创建原型对象
              Attachment  attachment = new Attachment(); //创建附件对象
              log_previous.setAttachment(attachment);  //将附件添加到周报中
              try
              {
                     log_new =  log_previous.deepClone(); //调用深克隆方法创建克隆对象                  
              }
              catch(Exception e)
              {
                     System.err.println("克隆失败!");
              }
              //比较周报
              System.out.println("周报是否相同? " + (log_previous ==  log_new));
              //比较附件
              System.out.println("附件是否相同? " +  (log_previous.getAttachment() == log_new.getAttachment()));
       }
}
      编译并运行程序,输出结果如下:
周报是否相同?  false
附件是否相同?  false


分享到:
评论

相关推荐

    设计模式之原型模式

    java 23种设计模式之原型模式:用原型实例指定创建对象的种类,并通过复制、克隆这些原型创建新的对象。

    java设计模式【之】原型模式、深拷贝与浅拷贝【源码】【场景:克隆羊】

    java设计模式【之】原型模式、深拷贝与浅拷贝【源码】【场景:克隆羊】 * 原型模式(Prototype) * 实现方式: * 需要被克隆的 class类, 重写Object中的clone()方法,并实现Cloneable接口(否则报错 ...

    设计模式_原型模式.zip

    这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。例如,一个对象需要在一个高...

    design-pattern-java.pdf

    基础知识 基础知识设计模式概述 从招式与内功谈起——设计模式概述(一) 从招式与内功谈起——设计模式概述(二) 从招式与内功谈起——设计模式概述(三) 面向对象设计原则 面向对象设计原则之单一职责原则 面向...

    C# 设计模式系列教程-原型模式

     2.2 具体原型类(Concrete Prototype): 及实现了克隆接口的具体原型类 3. 实例:求职网站上现在都支持多份简历,如果每创建一份简历都要从头至尾地填写一遍,那也是非常让人沮丧的事。其实针对我们的求职岗位的...

    设计模式代码和报告

    3.2原型模式是一种创建型设计模式,Prototype模式允许一个对象再创建另外一个可定制的对象,根本无需知道任何如何创建的细节,工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求...

    原型模式(Prototype Pattern)原理图

    原型模式是一种创建型设计模式,它通过复制一个现有的对象来创建新的对象,而不是通过调用构造函数的方式。这种方式可以在运行时动态地创建和修改对象,而不需要知道具体的创建细节 。 原型模式的基本概念包括以下...

    Java设计模式之原型模式.docx

    浅克隆 :克隆出来的对象实例一模一样,对象的属性如果是引用数据类型,那么他么指向同一个地址值。无论是修改原来的对象,还是修改克隆出来的对象,只要是引用数据类型修改了,那么两个对象同时被修改,因为他们...

    PHP设计模式之原型设计模式原理与用法分析

    原型设计模式使用一种克隆技术来复制实例化的对象,新对象是通过复制原型实例创建的。原型设计模式的目的是通过使用克隆以减少 实例化对象的开销。 在原型设计模式中,Client类是不可缺少的一部分。 PHP有一个内置的...

    Java设计模式 版本2

    对象的克隆——原型模式,复杂对象的组装与创建——建造者模式,不兼容结构的协调——适配器模式,处理多维度变化——桥接模式,树形结构的处理——组合模式,扩展系统功能——装饰模式,深入浅出外观模式,实现对象...

    精通python设计模式与源码

    首部分介绍处理对象创建的设计模式,包括工厂模式、建造者模式、原型模式;第二部分介绍处理一个系统中不同实体(类、对象等)之间关系的设计模式,包括外观模式、享元模式等;第三部分介绍处理系统实体之间通信的...

    Java设计模式——原型模式

    原型模式Java设计模式——原型模式概念使用场景Java里的克隆代码理解prototype(原型)问题总结优缺点模型优点模型缺点 概念 ​ 原型模式是创建型模式的最后一种,讲到原型模式就不得不提到克隆这个词,克隆这个词...

    Android编程设计模式之原型模式实例详解

    本文实例讲述了Android编程设计模式之原型模式。分享给大家供大家参考,具体如下: 一、介绍 原型模式是一个创建型的模式。原型二字表明了该模型应该有一个样板实例,用户从这个样板对象中复制出一个内部属性一致的...

    PHP设计模式之原型模式定义与用法详解

    原型设计模式(Prototype Design Pattern)很有意思, 因为它使用了一种克隆技术来复制实例化的对象. 新对象是通过复制原型实例来创建的. 在这里, 实例是批实例化的具体类.原型设计模式的目的是通过使用克隆来减少实例...

    GoF 的 23 种设计模式

    GoF 的 23 种设计模式的分类,现在对各个模式的功能进行介绍。 单例(Singleton)模式:某个类只能生成一个实例,该类提供了一个全局访问点供外部获取该实例,其拓展是有限多例模式。 原型(Prototype)模式:将一...

    C#23种设计模式_示例源代码及PDF

    原始模型模式: 原始模型模式 通过给出一个原型对象来指明所要创建的对象的类型,然后用复制这个原 型对象的方法创建出更多同类型的对象。 原始模型模式允许动态的增加或减少产品类, 产品 类不需要非得有任何事先...

    JavaScript设计模式之原型模式分析【ES5与ES6】

    从设计模式的角度讲,原型模式是用于创建对象的一种模式,若需要创建一个对象,一种方法是先指定其类型,然后通过类来创建这个对象,另一种方法是通过原型来创建,不必关心对象的具体类型,而是找到一个对象,然后...

    javascript设计模式 – 原型模式原理与应用实例分析

    本文实例讲述了javascript设计模式 – 原型模式原理与应用。分享给大家供大家参考,具体如下: 介绍:在日常的开发过程中,我们经常会利用到前端模板引擎来做页面渲染,因为存在很多页面结构相同,内容不同的场景。...

    python-patterns-收集了 Python 常用的设计模式-python

    evaluation Python池中延迟评估的属性模式预先实例化并维护一组相同类型的实例原型使用工厂和原型的克隆为新实例(如果实例化成本高)结构模式:模式描述3层数据业务逻辑表示分离(严格关系)适配器使用白名单桥使一...

    设计模式(十)之原型模式.zip

    原型模式:就是从一个对象再创建另一个可定制的对象,而且不需要知道任何创建的细节。 重写抽象类中的Clone方法或者重写ICloneable中的Clone方法。 也就是说:要实现克隆的这个类,必须实现其Clone方法。

Global site tag (gtag.js) - Google Analytics