java设计模式之原型模式

原创 2016年08月29日 21:13:46

首先来看其定义specify the kinds of objects to create using a prototypical instance, and create new objects by coping this protype。一句话总结就是采用复制已有对象实例来产生新的对象实例就被称为原型模式
java系统中,一个类可以通过复制实现生成新的对象,必须继承Cloneabel接口。事实上,Cloneable接口并不包含任何方法,它只是作为一种“标记”特征,告诉JVM,继承了该接口的对象可能可以调用clone方法复制产生新的对象。之所以说可能可以是因为该类必须覆写clone方法,才可以真的被clone。此处需要说明的是,Cloneabel接口不不包含任何方法,clone方法是来源于Object父类
示例代码如下:

public class CloneModel implements Cloneable{

    @Override
    protected CloneModel clone(){
        CloneModel cloneModel = null;
        try{
            cloneModel = (CloneModel)super.clone();
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
        return cloneModel;
    }

    public static void main(String [] args){
        CloneModel cloneModel = new CloneModel();
        CloneModel cloneModel1 = cloneModel.clone();
    }
}

clone方式相对new方式产生新的对象实例的优点在于,前者是直接对内存中二进制流的复制而不需要通过构造器生成对象,其效率自然更高一些。也由于前者产生一个新的对象时,并不执行构造函数,所以它也可以逃避构造函数的约束。谈到这里,不免想到我们前面的单例模式,在后面会讲到,只要不手动复制其被final关键字修饰的成员变量,如果该单例模式实现了Cloneable接口且覆写了clone()方法(当然我们肯定不会这么做),我们将打破单例模式的限制。
既然是通过复制实现的创建新的对象,我们不免想到该对象所附属的成员变量值会不会一同被复制呢?下面用一个例子说明:

public class CloneModel implements Cloneable{
    private ArrayList<String> arrayList = new ArrayList<String>();
    private String str;
    private int num_int = 0;
    private Integer num_integer = 0;

    public String getArrayList() {
        return arrayList.toString();
    }

    public void setArrayList(String str) {
        this.arrayList.add(str);
    }

    public String getStr() {
        return str;
    }

    public void setStr(String str) {
        this.str = str;
    }

    public int getNum_int() {
        return num_int;
    }

    public void setNum_int(int num_int) {
        this.num_int = num_int;
    }

    public Integer getNum_integer() {
        return num_integer;
    }

    public void setNum_integer(Integer num_integer) {
        this.num_integer = num_integer;
    }

    @Override
    protected CloneModel clone(){
        CloneModel cloneModel = null;
        try{
            cloneModel = (CloneModel)super.clone();
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
        return cloneModel;
    }

    public static void main(String [] args){
        //原始对象赋值
        CloneModel model = new CloneModel();
        model.setArrayList("First");
        model.setNum_int(1);
        model.setNum_integer(1);
        model.setStr("First");
        //打印复制后的对象各成员变量值
        System.out.println("clone后,clone对象值:");
        CloneModel cloneModel = model.clone();
        System.out.println(cloneModel.getArrayList());
        System.out.println(cloneModel.getNum_int());
        System.out.println(cloneModel.getNum_integer());
        System.out.println(cloneModel.getStr());
        //改变复制后的对象各成员变量值
        cloneModel.setArrayList("Second");
        cloneModel.setNum_int(2);
        cloneModel.setNum_integer(2);
        cloneModel.setStr("Second");
        //打印原始对象成员变量值
        System.out.println("改变clone对象值之后,原始对象值:");
        System.out.println(model.getArrayList());
        System.out.println(model.getNum_int());
        System.out.println(model.getNum_integer());
        System.out.println(model.getStr());


    }
}

在例子中,我们定义了四个成员变量,并分别在复制前改变原始对象赋值以及改变clone对象赋值,先后打印复制后的对象值以及原始对象值,结果如下:
这里写图片描述

为什么我们改变复制得到的对象的成员变量,结果原始对象的部分成员变量值也随之发生了改变呢?
原因在于,Object类的clone()方法所实现的复制,在成员变量的复制上,它只复制了值传递变量的值,并为之开辟了新的内存空间,也就是这些值引用的成员变量与之前的原始对象再无半点瓜葛。而针对引用传递的变量,它只复制了其引用而并未为该变量创建新的内存空间,也就是说,它与原始对象共享了引用传递变量的内存区域,就有了上面的“大家一起变”的情况。
若非得将引用传递类型的成员变量搞成“你是你 我是我”,像值传递变量一样的话,只需要在调用super.clone()方法时,单独调用该引用传递对象成员变量的clone()方法,并将其赋值到新的clone对象的成员变量上。如下:

@Override
    protected CloneModel clone(){
        CloneModel cloneModel = null;
        try{
            cloneModel = (CloneModel)super.clone();
            cloneModel.arrayList = (ArrayList<String>)this.arrayList.clone();
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
        return cloneModel;
    }

需要注意的是,若该变量恰好被final关键字修饰,则编译器将报错。此时,最好做法是去除final 关键字。

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

Java技术_每天掌握一种设计模式(006)_使用场景及简单实例(创建型:原型模式)

模式描述 用原型实例指定创建对象的种类,并且通过拷贝来创建新的对象。 2.模式作用 可以一定程度上解耦,消费者和对象的构造过程隔离开,对象如何构造与消费者完全无关。 可以一定程度提升效率,复杂对...

设计模式(五)----- 原型模式(Prototype)----(JAVA版)

用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象      Prototype模式允许一个对象再创建另外一个可定制的对象,根本无需知道任何如何创建的细节,工作原理是:通过将一个原型对象...

Java设计模式四: 原型模式(Prototype Pattern)

Java设计模式四: 原型模式(Prototype Pattern)   原型模式是一种创建型设计模式,它通过复制一个已经存在的实例来返回新的实例,而不是新建实例.被复制的实例就是我们所称的原型,这...
  • zoubf
  • zoubf
  • 2016年01月22日 09:56
  • 262

java设计模式学习笔记--原型模式(浅克隆和深克隆)

1. 什么是原型模式原型模式属于对象的创建模式。。原型模式允许你通过复制现有的实例来创建新的实例。 这个模式的重点在于,客户端的代码在不知道要实例化何种特定类的情况下,可以制造出新的实例。在java...

设计模式学习笔记---原型模式prototype(Java版)

一、场景 克隆羊多利 二、本质 通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式节约时间。就是java中的克隆技术,以某个对象为原型,复制出新的对象。新的对象具备原型对...

java设计模式5--原型模式(Prototype)

本文地址:http://www.cnblogs.com/archimedes/p/java-prototype-pattern.html,转载请注明源地址。 原型模式 用原型实例指定创建对...

java设计模式—原型模式

原型模式、Java设计模式

Java设计模式学习04——原型模式

原型模式  当我们需要构建一个与已经存在对象相似时,再通过new去产生一个新对象需要非常繁琐的数据准备或访问权限,而这时就可以用到原型模式,原型模式实现就是Java中的克隆技术,以某个对象为原型,复制...
  • xu__cg
  • xu__cg
  • 2016年10月26日 10:38
  • 480

java设计模式---Prototype Pattern---原型模式(复制建立对象)

在我们建立Something类的实例时,会使用下面的表达式:  new Something(); 利用new指定类名可以产生对象实例。但是在有些情况下不靠new来产生实例是方便和必要的: 1. ...
  • ydd326
  • ydd326
  • 2011年09月08日 16:40
  • 603

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

用原型实例指定创建对象的种类,并且同过拷贝这些原型创建新的对象。 在java中提供了clone方法来实现对象的克隆,那么先看下clone应满足的条件(要实现克隆该类必需implements Clon...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:java设计模式之原型模式
举报原因:
原因补充:

(最多只允许输入30个字)