java原型模式

原型模式(Prototype):用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

原型模式结构图

通俗来说:原型模式就是深拷贝和浅拷贝的实现。

浅拷贝

只实现了值拷贝,对于引用对象还是指向原来的对象。

  • 父类实现clone方法,子类没有实现clone方法,其效果是浅拷贝。
  • 父类实现clone方法,子类也实现clone方法,本来我想应该是深拷贝了,没想到也是浅拷贝
package com.prototype;
import java.io.Serializable;

public class Work implements Serializable,Cloneable{
    private static final long serialVersionUID = 207835812839542204L;
    private String job;
    private double salary;
    public Work(String job,double salary) {
        this.job = job;
        this.salary = salary;
    }
    @Override
    public String toString() {
        return "Work [job=" + job + ", salary=" + salary + "]";
    }
    public String getJob() {
        return job;
    }
    public void setJob(String job) {
        this.job = job;
    }
    public double getSalary() {
        return salary;
    }
    public void setSalary(double salary) {
        this.salary = salary;
    }
}
package com.prototype;

import java.io.Serializable;

public class User implements Serializable,Cloneable{
    private static final long serialVersionUID = -2260332138558500447L;

    private String name = "";
    private Work work = null;

    public User(String name,String job,double salary) {
        this.name=name;
        work = new Work(job, salary);
    }

    public void changeJob(String job){
        this.work.setJob(job);
    }
    /*只需要实现Cloneable接口,覆写clone方法,此处clone方法可以改成任意的名称,
    因为Cloneable接口是个空接口,你可以任意定义实现类的方法名,如cloneA或者cloneB。
    重点是super.clone()这句话,super.clone()调用的是Object的clone()方法,而在Object类中,clone()是native的。
    */
    //浅复制:将一个对象复制后,基本数据类型的变量都会重新创建,而引用类型,指向的还是原对象所指向的。
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    @Override
    public String toString() {
        return "User [name=" + name + ", work=" + work + "]";
    }

}
package com.prototype;

public class Main {

    public static void main(String[] args) {
        try {
            User user1 = new User("zhangsan","ceo",100000);
            User user2 = (User) user1.clone();
            System.out.println(user1);
            System.out.println(user2);
            System.out.println("修改job");
            user2.changeJob("cfo");
            System.out.println(user1);
            System.out.println(user2);

        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }
}
//结果
User [name=zhangsan, work=Work [job=ceo, salary=100000.0]]
User [name=zhangsan, work=Work [job=ceo, salary=100000.0]]
修改job
User [name=zhangsan, work=Work [job=cfo, salary=100000.0]]
User [name=zhangsan, work=Work [job=cfo, salary=100000.0]]

深拷贝

即实现了值拷贝,也实现了对引用对象的拷贝。

  • 法一
    //深复制:将一个对象复制后,不论是基本数据类型还有引用类型,都是重新创建的。
    //实现深复制,需要采用流的形式读入当前对象的二进制输入,再写出二进制数据对应的对象。
    public Object deepClone() throws IOException, ClassNotFoundException{
        //写入当前对象的二进制流
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(this);

        //读入二进制流产生的新对象
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
        return ois.readObject();
    }
  • 法二
    //将User的拷贝方法修改为下面的方法。
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Work w = (Work) work.clone();//对其引用变量进行拷贝
        User u = (User)super.clone();//自身拷贝
        u.work = w;//引用变量重新赋值。
        return u;
    }

===================================================

  • 定义

    用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。

  • 使用场景

    原型模式被用在频繁调用且极其相似的对象上,它会克隆对象并设置改变后的属性,而且消耗的资源较少。

  • 代码举例实现

ProtoTypeImpl.java

 package com.design.prototype;

public class ProtoTypeImpl implements Cloneable{

    private int shallowClone;

    private DeepClone deepClone = new DeepClone();

    public ProtoTypeImpl() {
        System.out.println("construct is called");
    }

    public void print() {
        // TODO Auto-generated method stub
        System.out.println(shallowClone);
        System.out.println(deepClone.getS());
    }

    @Override
    protected ProtoTypeImpl clone(){
        // TODO Auto-generated method stub
        try{
            ProtoTypeImpl protoTypeImp =  (ProtoTypeImpl) super.clone();
            //protoTypeImp.shallowClone = this.shallowClone;
            //protoTypeImp.deepClone = this.deepClone.clone();
            return protoTypeImp;
        }catch(Exception e){
            e.printStackTrace();
            return null;
        }

    }

    public void setShallowClone(int shallowClone) {
        this.shallowClone = shallowClone;
    }

    public void setS(String s){
        deepClone.setS(s);
    }
}

DeepClone.java

package com.design.prototype;

public class DeepClone implements Cloneable{
    private String s;

    public String getS() {
        return s;
    }

    public void setS(String s) {
        this.s = s;
    }

    @Override
    protected DeepClone clone(){
        // TODO Auto-generated method stub
        try {
            return (DeepClone)super.clone();
        } catch (CloneNotSupportedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }
}

App.java

package com.design.prototype;

public class App {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        ProtoTypeImpl protoTypeImp = new ProtoTypeImpl();
        protoTypeImp.setShallowClone(1);
        protoTypeImp.setS("deep clone");
        protoTypeImp.print();
        System.out.println("-------------");
        ProtoTypeImpl protoTypeImp2 = protoTypeImp.clone();
        protoTypeImp2.setShallowClone(2);
        protoTypeImp2.setS("deep clone 2");

        protoTypeImp2.print();
        System.out.println("-------------");
        protoTypeImp.print();
    }

}
  • 结果分析

运行结果1.png

  1. 这个现象主要是由于深浅复制引起的,普通类型的数据没有问题,而对象类型则有问题。同时我们应该注意到clone的时候构造函数是不会被调用的。
  2. 去掉ProtoTypeImpl.clone的两行注释(第一行没什么所谓,但是还是加上,有个对比)

    运行结果2.png

  3. 总结优缺点

    • 优点
      原型模式是在内存二进制流的拷贝,要比直接 new 一个对象性能好很多,特别是要在一个循环体内产生大量的对象时,原型模式可以更好地体现其点。
    • 缺点
      使用过程中要切记构造函数不会被调用,所以在构造函数完成的操作应该多加处理,还有深浅复制的问题

文/lguipeng(简书作者)
原文链接:http://www.jianshu.com/p/062023c33d77
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

时间: 2024-08-07 16:33:50

java原型模式的相关文章

Java原型模式(Prototype模式)

Prototype模式定义:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. Prototype模式允许一个对象再创建另外一个可定制的对象,根本无需知道任何如何创建的细节,工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建. 如何使用原型模式 因为Java中的提供clone()方法来实现对象的克隆,所以Prototype模式实现一下子变得很简单.以勺子为例: public abstract class Abstrac

Java 原型模式(克隆模式)

  Java 的设计模式有 23 种,前段时间小编已经介绍了单例模式,由于我们在学习 Spring 的时候在 bean 标签的学习中碰到了今天要讲的原型模式,那么小编就已本文来介绍下原型模式. 原型模式  在java中我们知道通过new关键字创建的对象是非常繁琐的(类加载判断,内存分配,初始化等),在我们需要大量对象的情况下,原型模式就是我们可以考虑实现的方式.  原型模式我们也称为克隆模式,即一个某个对象为原型克隆出来一个一模一样的对象,该对象的属性和原型对象一模一样.而且对于原型对象没有任何

Java原型模式(思维导图)

图1 原型模式[点击查看大图] 1,原型对象 public class Prototype implements Cloneable{ public Prototype clone(){ Prototype prototype=null; try{ prototype=(Prototype)super.clone(); }catch (CloneNotSupportedException e){ e.printStackTrace(); } return prototype; } } class

Java原型模式之浅拷贝-深拷贝

一.是什么? 浅拷贝:对值类型的成员变量进行值的复制,对引用类型的成员变量仅仅复制引用,不复制引用的对象 深拷贝:对值类型的成员变量进行值的复制,对引用类型的成员变量也进行引用对象的复制 内部机制: (1)关于Object类的clone方法 默认实现为"浅拷贝",重写Object类中的clone方法.Java中全部类的父类都是Object类,Object类中有一个clone方法.作用是返回对象的一个拷贝,可是其作用域是protected类型的,一般的类无法调用,因此Prototype类

java 原型模式之浅拷贝

浅拷贝:java Ojbect类提供的clone只是拷贝本对象,其对象内部的数组和引用对象等都不拷贝,还是指向原生对象的内部元素地址. 类引用的成员变量必须满足两个条件才不会被拷贝:1.是类的成员变量而不是方法内变量:2必须是一个可变的引用对象,而不是一个原始类型或者不可变对象(包括int.long.char等及其对象类型[Integer.Long].String) 测试代码: import java.util.ArrayList; import java.util.List; public c

iOS与Java原型设计模式,欢迎扫二维码加入订阅号进行讨论

什么是原型模式 什么时候用到原型模式 原型模式有那些优缺点 oc与java语法上原型模式有那些异同及简单的例子 首先看什么是原型模式: java:Specify the kinds of objects to create using a prototypical instance, and create new objects by copying this prototype.(用原型实例制定创建对象的种类,并且创建一个新的对象从原型对象拷贝而来.) iOS:客户端知道抽象prototype

设计模式解密(18)- 原型模式

1.简介 定义:用原型实例指定创建对象的种类,并且通过拷贝这些原型来创建新的对象. 功能:①是通过克隆来创建新的对象实例:②是为克隆出来的新的对象实例复制原型实例属性的值. 本质:通过克隆来创建新的对象实例. 英文:Prototype 类型:创建型 2.类图及组成 (引)类图: 组成: Prototype:声明一个克隆自身的接口,用来约束想要克隆自己的类,要求它们都要实现这里定义的克隆方法. ConcretePrototype:实现Prototype接口的类,这些类真正实现了克隆自身的功能. C

《JAVA与模式》之原型模式

在阎宏博士的<JAVA与模式>一书中开头是这样描述原型(Prototype)模式的: 原型模式属于对象的创建模式.通过给出一个原型对象来指明所有创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象.这就是选型模式的用意. 原型模式的结构 原型模式要求对象实现一个可以"克隆"自身的接口,这样就可以通过复制一个实例对象本身来创建一个新的实例.这样一来,通过原型实例创建新的对象,就不再需要关心这个实例本身的类型,只要实现了克隆自身的方法,就可以通过这个方法来获取新

java设计模式---原型模式

原型模式也是创建型的设计模式,通过拷贝原型创建新的对象,理解原型模式必须理解java中的浅复制和深复制.复制也称为克隆.会发生深拷贝的有java中的8中基本类型以及他们的封装类型,另外还有String类型.其余的都是浅拷贝. 浅克隆:浅克隆仅仅克隆所考虑的对象,而不克隆它所引用的对象. 深克隆:深克隆不仅克隆所考虑的对象,也克隆它所引用的对象. 它的核心是就是原型类Prototype.Prototype类需要具备以下两个条件: 实现Cloneable接口.在java语言有一个Cloneable接