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设计模式(五) 原型模式详解

在开发过程中,有时会遇到为一个类创建多个实例的情况,这些实例内部成员往往完全相同或有细微的差异,而且实例的创建开销比较大或者需要输入较多参数,如果能通过复制一个已创建的对象实例来重复创建多个相同的对象...
  • u013916933
  • u013916933
  • 2016年06月04日 16:22
  • 3125

Java设计模式——原型模式

原型模式是为了解决一些不必要的对象创建过程。当Java JDK中提供了Cloneable接口之后,原型模式就变得异常的简单了。虽然由于Cloneable的引入使用程序变得更简单了,不过还是有一些需要说...
  • u013761665
  • u013761665
  • 2016年03月03日 13:50
  • 1993

设计模式之五:原型模式—对象的克隆

通过一个原型对象克隆出多个一模一样的对象,称为原型模式(Prototype Pattern) 克隆后的对象对原对象独立,对克隆后的对象进行修改不对原对象产生影响 一、原型模...
  • wujunwen
  • wujunwen
  • 2016年09月22日 15:27
  • 242

23中设计模式之_原型模式(深/浅拷贝)

前言原型模式其实java Object中已经提供了一个Clone( )方法,平时很少用到,最近读Retrofit源码时候看到有这种使用方式。 定义原型模式就是在系统clone()标记的基础上,对Cl...
  • o279642707
  • o279642707
  • 2017年03月14日 17:51
  • 900

<六>读<<大话设计模式>>之原型模式

原型模式也是很简单的一种模式,对于java来说已经有相应的接口了(Cloneable)。关于原型模式>是以投放简历作为例子讲解的,即我要投放很多简历,其实每个简历都一样,所以只要我写好一份,其他的复制...
  • jzhf2012
  • jzhf2012
  • 2014年10月30日 20:58
  • 1066

JAVA设计模式之原型模式

定义:用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。 类型:创建类模式 类图: 原型模式主要用于对象的复制,它的核心是就是类图中的原型类Prototype。Prototype...
  • jason0539
  • jason0539
  • 2014年04月08日 08:22
  • 15435

设计模式(创建型)之原型模式(Prototype Pattern)

要理解原型原型模式必须先理解Java里的浅复制和深复制。有的地方,复制也叫做克隆。Java提供这两种克隆方式。 因为Java中的提供clone()方法来实现对象的克隆,所以Prototype模式实现一...
  • yanbober
  • yanbober
  • 2015年04月29日 11:28
  • 3038

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

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

设计模式--原型模式

1.设计模式分类         所谓设计模式,是前人在开发过程中总结的经验。各自有各自的使用情况。分类条件不同 设计模式的分类也不尽相同。编程之道中大致分类如下 创建型 包括 单例设计模式,简单工厂...
  • a316212802
  • a316212802
  • 2015年11月13日 18:45
  • 1001

PHP设计模式——原型模式

声明:本系列博客参考资料《大话设计模式》,作者程杰。        用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。Prototype模式允许一个对象再创建另外一个可定制的对象,根本无...
  • jhq0113
  • jhq0113
  • 2015年04月25日 20:59
  • 1861
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:java设计模式之原型模式
举报原因:
原因补充:

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