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

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

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

定义很简单,就是通过实例制定种类,通过拷贝创建对象,该模式适用于以下场景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种创建型模式一一介绍完毕。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值