设计模式之建造型-原型模式(5)

来源:互联网 发布:2017程序员 编辑:程序博客网 时间:2024/05/18 01:12

今天介绍原型模式,也是最后一个建造型设计模式

定义:通过给出一个原型对象来指明所有创建的对象的类型,然后用复制这个原型对象的方法来创建出更多的新对象。

定义很简单,就是通过实例制定种类,通过拷贝创建对象,该模式适用于以下场景1,对象的创建十分复杂。2在运行的过程中并不知道对象的具体类型,可以使用原型模式来

创建一个相同类型的对象出来。

在Java中,实现原型模式很简单,即实现cloneable接口,然后使用object类提供的clone方法进行拷贝,而拷贝又分为浅拷贝和深度拷贝下面我们来用代码实现浅拷贝

public class Student implements  Cloneable {   public    StudentMessage studentMessage;    public void setStudentMessage (StudentMessage studentMessage){        this.studentMessage=studentMessage;    }    @Override    public Student clone()  {        Student student= null;        try {            student = (Student) super.clone();        } catch (CloneNotSupportedException e) {            e.printStackTrace();        }        return student;    }}public class StudentMessage{    String name;    String ID;    public StudentMessage(String name, String ID) {        this.name = name;        this.ID = ID;    }}

测试类

public class Test {    public static void main(String[] args) {        Student phoneA=new Student();        phoneA.setStudentMessage(new StudentMessage("zhangsan","1234"));        Student phoneB = phoneA.clone();        System.out.print("phoneA:"+phoneA.toString());        System.out.print("  phoneB:"+phoneB.toString());        System.out.print("  StudentMessageA:"+phoneA.studentMessage.toString());        System.out.print("  StudentMessageB:"+phoneB.studentMessage.toString());    }}

结果输出:

上面即为最简单的原型模式的实现,其中浅拷贝的基本变量都会重新创建,而引用类型,指向还是原来的对象所指向,上面例子中的student还是指向原来的。值得注意的是,运用clone()方法创建出来的对象的构造方法并不会执行。

深拷贝

深拷贝会使引用类型都重新创建,在java中有两种写法,一种为需要克隆对象所使用的所有引用类型都实现cloneable接口,然后重写object类提供的clone方法进行拷贝。

public class StudentMessage implements Cloneable{        String name;        String ID;        public StudentMessage(String name, String ID) {            this.name = name;            this.ID = ID;        }    @Override    protected StudentMessage clone() throws CloneNotSupportedException {        return  (StudentMessage) super.clone();    }}public class Student implements  Cloneable {   public    StudentMessage studentMessage;    public void setStudentMessage (StudentMessage studentMessage){        this.studentMessage=studentMessage;    }    @Override    public Student clone()  {        Student student= null;        try {            student = (Student) super.clone();             studentMessage = student.studentMessage.clone();        } catch (CloneNotSupportedException e) {            e.printStackTrace();        }        return student;    }}

测试:

public class Test {    public static void main(String[] args) {        Student phoneA=new Student();        phoneA.setStudentMessage(new StudentMessage("zhangsan","1234"));        Student phoneB = phoneA.clone();        System.out.print("phoneA:"+phoneA.toString());        System.out.print("  phoneB:"+phoneB.toString());        System.out.print("  StudentMessageA:"+phoneA.studentMessage.toString());        System.out.print("  StudentMessageB:"+phoneB.studentMessage.toString());    }}

输出:

phoneA:com.wujie.demo.clone.Student@266474c2

phoneB:com.wujie.demo.clone.Student@6f94fa3e

StudentMessageA:com.wujie.demo.clone.StudentMessage@5e481248

StudentMessageB:com.wujie.demo.clone.StudentMessage@66d3c617

我们可以看到,其中引用类型被重新创建了,但是,假如我们引用的类型里,又有新的引用类似的时候,用这种方法完成深度拷贝会无比的麻烦,这个时候我们利用序列化进行拷贝

   public class StudentMessage implements Serializable{        String name;        String ID;        public StudentMessage(String name, String ID) {            this.name = name;            this.ID = ID;        }}public class Student implements Serializable {   public    StudentMessage studentMessage;    public void setStudentMessage (StudentMessage studentMessage){        this.studentMessage=studentMessage;    }    @Override    public Student clone()  {        Student student=null;        try {            ByteArrayOutputStream  bos=new ByteArrayOutputStream();            ObjectOutputStream oos=new ObjectOutputStream(bos);            oos.writeObject(this);            ByteArrayInputStream bais=new ByteArrayInputStream(bos.toByteArray());            ObjectInputStream ois=new ObjectInputStream(bais);             student = (Student) ois.readObject();        } catch (IOException e) {            e.printStackTrace();        }catch (ClassNotFoundException e) {            e.printStackTrace();        }      return  student;    }}

我们注意到,所有的引用类都要继承serializable接口才可以序列化

测试:

public class Test {    public static void main(String[] args) {        Student phoneA=new Student();        phoneA.setStudentMessage(new StudentMessage("zhangsan","1234"));        Student phoneB = phoneA.clone();        System.out.print("phoneA:"+phoneA.toString());        System.out.print("  phoneB:"+phoneB.toString());        System.out.print("  StudentMessageA:"+phoneA.studentMessage.toString());        System.out.print("  StudentMessageB:"+phoneB.studentMessage.toString());    }}

输出:

phoneA:com.wujie.demo.clone.Student@355da254

phoneB:com.wujie.demo.clone.Student@12edcd21

StudentMessageA:com.wujie.demo.clone.StudentMessage@4dc63996

StudentMessageB:com.wujie.demo.clone.StudentMessage@34c45dca

可以看到,利用序列化的方式可以相对简单的完成深度克隆,序列化就是将对象写进流的过程,写进流的过程会对原有对象进行拷贝克隆

到此就将5种创建型模式一一介绍完毕。

原创粉丝点击