`
wangwei3
  • 浏览: 121012 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

设计模式之原型模式prototype

阅读更多
所谓的原型模式,就是用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
1.首先需要了解java的clone技术
我理解的很简单,无非是把一个对象进行复制粘贴。那么,来看一下JAVA语言中是如何来实现的这个步骤的。我们依次需要知道以下这些事。

1.Object对象中有一个clone()方法。而且是protected。

2.继承于Object的类一般都可以实现这个方法(有特殊的,比如StringBuffer等,官方定的,不去研究它)。

3.想被clone的对象需要实现接口Cloneable。如果此对象的类不能实现接口Cloneable,则会抛出CloneNotSupportedExcetion。

4.所有的数组都被视为实现接口Cloneable。

5.clone分为浅clone(又称影子clone)和深clone。

6.Object类本身不实现接口Cloneable,所以在类为Object的对象上调用clone方法,将会导致在运行时抛出异常。

关键所在深克隆和浅克隆,那到底他们之间有什么区别呢?
首先看一下例子:

public abstract class CloneClass implements Cloneable {
	public int aInt;

	public Object clone() {
		CloneClass o = null;
		try {
			o = (CloneClass) super.clone();
		} catch (CloneNotSupportedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return o;
	}
}




public class UnCloneA {
	private int i;

	public UnCloneA(int ii) {
		i = ii;
	}

	public void doublevalue() {
		i *= 2;
	}

	public String toString() {
		return Integer.toString(i);
	}
}



public class CloneB implements Cloneable {
	public int aInt;
	public UnCloneA unCloneA = new UnCloneA(111);

	public Object clone() {
		CloneB o = null;
		try {
			o = (CloneB) super.clone();
		} catch (CloneNotSupportedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return o;
	}
}



public class Test {
	public static void main(String args[]) {
		CloneB b1 = new CloneB();
		b1.aInt = 11;
		System.out.println("before clone,b1.aInt = " + b1.aInt);
		System.out.println("before clone,b1.unCA = " + b1.unCloneA);
		CloneB b2 = (CloneB) b1.clone();
		b2.aInt = 22;
		b2.unCloneA.doublevalue();
		System.out.println("=================================");
		System.out.println("after clone,b1.aInt = " + b1.aInt);
		System.out.println("after clone,b1.unCA = " + b1.unCloneA);
		System.out.println("=================================");
		System.out.println("after clone,b2.aInt = " + b2.aInt);
		System.out.println("after clone,b2.unCA = " + b2.unCloneA);

	}
}


输出结果:

before clone,b1.aInt = 11
before clone,b1.unCA = 111
=================================
after clone,b1.aInt = 11
after clone,b1.unCA = 222
=================================
after clone,b2.aInt = 22
after clone,b2.unCA = 222

可见,当执行clone这个动作的时候,系统首先开辟一个和它一样的空间。然后分别对其内容进行复制。复制过程中,如果是基本类型,没什么说的,直接把值复制过来。如果不是基本类型,复制的则是该类型对象的引用。

这样的clone就是所谓的浅clone。那很显然,如果上面复制的过程中,对于非基本类型实现的不是一个引用复制,而是创建一个新的一样的对象(其实也是一个clone步骤),那么就是所谓的深clone。对于深度克隆只不过是clone的一种扩展,还有N深clone等等。对于这些,和我们要研究的原型模式没有多少关系。

1、浅克隆:

a. 提供一个类作为克隆的原型,该类实现了Clonable接口

b. 在该类中覆盖Object类的clone()方法,采用super.clone()方法完成克隆

c. 在外部使用场合先产生一个原型对象,然后调用其clone()方法产生克隆对象

2、深克隆:

a. 提供一个类作为克隆的原型,该类实现了Serializable接口

b. 在该类中覆盖Object类的clone()方法,采用序列化的方法完成克隆(对象流的读写)

c.在外部使用场合先产生一个原型对象,然后调用其clone()方法产生克隆对象




二、Prototype模式与深、浅克隆:

使用Object.clone()方法进行的克隆是“浅克隆”-被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。浅克隆的步骤如下:

①为了获取对象的一份拷贝,我们可以利用Object类的clone()方法。

②在派生类中覆盖基类的clone()方法,并声明为public。

③在派生类的clone()方法中,调用super.clone()。

④在派生类中实现Cloneable接口。


为什么我们在派生类中覆盖Object的clone()方法时,一定要调用super.clone()呢?在运行时刻,Object中的clone()要识别出你要复制的是哪一个对象,然后为此对象分配空间,并进行对象的复制,将原始对象的内容一一复制到新对象的存储空间中。

要实现“深克隆”-被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍。

深克隆需要使用Java中提供的对象串行化功能-即把要复制的对象写入到一个缓冲流,然后通过输入流读入,完成对象的复制

下面是深克隆与浅克隆的代码
public class SuperStar implements Cloneable, Serializable {
	public String name;
	public int height;
	public Skill mySkill;

	public Object clone() {
		Object o = null;
		try {
			o = super.clone();
		} catch (CloneNotSupportedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return o;
	}

	public Object deepClone() throws Exception {
		Object o = null;
		try {
			ByteArrayOutputStream bos = new ByteArrayOutputStream(); // (ByteArrayOutputStream)此类实现了一个输出流,其中
			// 的数据被写入一个字节数组。缓冲区会随着数据的不断写入而自动增长。
			ObjectOutputStream oos = new ObjectOutputStream(bos);
			oos.writeObject(this);  // 通过Serialization机制将自身写入该缓冲区

			// 找到刚才开辟的缓冲区准备读取
			ByteArrayInputStream bis = new ByteArrayInputStream(bos
					.toByteArray()); //
			ObjectInputStream ois = new ObjectInputStream(bis);
			 // 将刚才写入的内容读入一个新的对象
			o = ois.readObject();

			bos.close();
			oos.close();
			bis.close();
			ois.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return o;
	}

}


public class Skill implements Serializable{
	public int strength;
	public int jumping;
}


public class Test {
	public static void main(String args[]) throws Exception{
		SuperStar s1=new SuperStar();
		s1.name="姚明";
		s1.height=226;
		s1.mySkill=new Skill();
		s1.mySkill.jumping=50;
		s1.mySkill.strength=20;
		
		System.out.println(s1.name+"  " + s1.height +" "+s1.mySkill.jumping);
		
		SuperStar s2=(SuperStar) s1.clone();
		
//		SuperStar s2=(SuperStar) s1.deepClone();
		s2.name="潘长江";
		s2.height=100;
		s2.mySkill.jumping=10;
		s2.mySkill.strength=5;
		
		System.out.println(s2.name+"  " + s2.height+" " +s2.mySkill.jumping);
		System.out.println(s1.name+"  " + s1.height +" "+s1.mySkill.jumping);
	}
}


浅克隆 结果
姚明  226 50
潘长江  100 10
姚明  226 10


深克隆 结果

姚明  226 50
潘长江  100 10
姚明  226 50

JAVA中的clone方法,其实现是native的。这也就意味着它的执行效率是远高于new一个新对象的。所以,当需要生成大量相似对象的时候,可以考虑下应用clone,也就是原形模式。
分享到:
评论

相关推荐

    设计模式之Prototype(原型)

    "原型"(Prototype)设计模式是其中的一种,它的主要目标是通过复制现有的对象来创建新的对象,而不是通过构造函数来创建新实例。这种方法尤其适用于当创建新对象的过程复杂或者昂贵时,例如,当对象需要大量初始化...

    原型设计模式prototype

    **原型设计模式(Prototype Pattern)**是一种创建型设计模式,它允许我们通过复制现有的对象来创建新对象,而不是通过构造函数来实例化新对象。在面向对象编程中,当我们需要频繁地创建具有相同或相似属性的对象时,...

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

    Prototype模式允许一个对象再创建另外一个可定制的对象,根本无需知道任何如何创建的细节,工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建。...

    23种设计模式之Prototype模式代码

    **原型模式(Prototype模式)**是软件设计模式中的一个经典模式,属于创建型模式。它提供了一种通过复制现有的对象来创建新对象的方式,而无需知道具体创建过程的细节。这种模式在需要频繁创建相似对象时非常有用,...

    c++-设计模式之原型模式(Prototype Pattern)

    原型模式(Prototype Pattern)是一种创建型设计模式,允许通过复制现有对象来创建新对象,而不是通过类构造器。这种模式常用于需要频繁创建相似对象的场景,能够提高性能并减少内存使用。 原型模式的组成 原型接口...

    设计模式之原型模式

    原型模式是设计模式中的一种,它是Java 23种经典设计模式之一,主要用来提高对象创建的效率。在原型模式中,我们通过复制或克隆一个已经存在的对象来创建新的对象,而不是通过构造函数来创建。这种方法尤其适用于当...

    设计模式之Prototype

    在给定的文件"设计模式之Prototype(圆形).doc"中,可能详细阐述了如何将Prototype模式应用于创建圆形对象的例子。在这种情况下,可能会有一个Circle类作为具体原型,它实现了Prototype接口,并且提供了克隆圆形对象...

    JAVA设计模式chm文档

    设计模式之Prototype(原型) 设计模式之Builder 设计模式之Singleton(单态) 结构模式: 设计模式之Facade(外观) 设计模式之Proxy(代理) 设计模式之Adapter(适配器) 设计模式之Composite(组合) 设计模式之Decorator...

    设计模式C++学习之原型模式(Prototype)

    本篇文章将深入探讨“原型模式(Prototype)”这一经典的设计模式,它是面向对象设计的一个重要概念,尤其在C++编程中有着广泛的应用。 原型模式是一种创建型设计模式,它的核心思想是通过复制已有对象来创建新对象,...

    Prototype模式

    **原型模式(Prototype Pattern)**是一种创建型设计模式,它提供了一种通过复制已有对象来创建新对象的方式,而不是通过构造函数。在某些情况下,当创建新对象的成本非常高时(例如,对象需要大量的初始化操作或者从...

    android设计模式之原型模式

    本文将深入探讨Android设计模式中的“原型模式”(Prototype Pattern),并结合提供的"prototype"压缩包中的示例代码进行解析。 原型模式是一种创建型设计模式,它的主要思想是通过复制已有对象来创建新对象,而...

    Java设计模式之禅

    《Java设计模式之禅》是一本深入浅出讲解设计模式的书籍,书中不仅包含23种经典设计模式的案例,还详细介绍了设计模式背后的思想和原则,适合初学者以及对设计模式有一定了解的程序员阅读。本书旨在帮助读者理解如何...

    iOS设计模式之原型模式

    本文将深入探讨一种常见的设计模式——原型模式(Prototype Pattern),并结合具体的iOS应用场景进行解析。 原型模式是一种创建型设计模式,它的主要思想是通过复制已有对象来创建新对象,而不是通过构造函数来创建...

    设计模式文档 chm

    设计模式之Prototype(原型) 设计模式之Builder 设计模式之Singleton(单态) 结构模式: 设计模式之Facade(外观) 设计模式之Proxy(代理) 设计模式之Adapter(适配器) 设计模式之Composite(组合) 设计模式之Decorator...

    JavaScript设计模式与开发实践.pdf

    第二部分是核心部分,通过一步步完善的代码示例,由浅入深地讲解了16个设计模式,包括 singleton模式、Factory模式、Abstract Factory模式、Builder模式、Prototype模式、Adapter模式、Bridge模式、Composite模式、...

    设计模式之原型模式Java实现和类设计图

    原型模式(Prototype Pattern)是其中一种行为设计模式,主要用于对象创建。它通过复制已有对象来创建新对象,而不是通过传统的构造函数来创建。在Java中,原型模式可以有效地提高性能,特别是在创建复杂对象时。 #...

    设计模式的原型模式的例子

    原型模式(Prototype Pattern)是软件设计模式中的一种结构型模式,它的主要目的是通过复制已有对象来创建新对象,从而减少创建新对象的成本。在原型模式中,类的实例化过程被替换为对已有实例的克隆操作,尤其适用...

    小D深入浅出设计模式+框架源码剖析实战

    ├─第一章 旭瑶-小滴...│ 5.1-创建型设计模式-Prototype原型设计模式实战《上》.mp4 │ 5.2-创建型设计模式-Prototype原型设计模式实战《下》.mp4 │ 6.1-接口之间的桥梁-适配器设计模式你知道多少.mp4 │ 6.4

Global site tag (gtag.js) - Google Analytics