您的位置:首页 > 编程语言 > Java开发

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

2015-02-28 22:21 891 查看
一、场景

克隆羊多利

二、本质

通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式节约时间。就是java中的克隆技术,以某个对象为原型,复制出新的对象。新的对象具备原型对象的特点。效率高,避免了重新执行构造过程的步骤。

克隆类似于new,但不同于new.new创建新的对象属性采用的是默认值。克隆出的对象的属性值完全和原型对象相同。并且克隆出的新对象不会影响原型对象。然后,再修改克隆对象的值。

三、具体操作

实现Cloneable接口

重写Object的clone方法。

四、示例



1、浅克隆

package com.lgd.prototype;

import java.util.Date;

public class LowSleep implements Cloneable{
	private String nameString;
	private Date birthday;
	public LowSleep() {
		// TODO Auto-generated constructor stub
	}
	
	public LowSleep(String nameString, Date birthday) {
		super();
		this.nameString = nameString;
		this.birthday = birthday;
	}

	@Override
	protected Object clone() throws CloneNotSupportedException {
		Object object = super.clone(); //直接调用object对象的clone()方法
		return object;
	}

	public String getNameString() {
		return nameString;
	}

	public void setNameString(String nameString) {
		this.nameString = nameString;
	}

	public Date getBirthday() {
		return birthday;
	}

	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}
}


package com.lgd.prototype;

import java.sql.Date;

/**
 * 测试原型模式(浅克隆)
 * @author Administrator
 * 克隆 --->  对象不同,但是内容一样。其中的内容可以修改。
 */
public class ClientLowcopy {
	public static void main(String[] args) throws CloneNotSupportedException {
		Date date = new Date(12324354543543L);
		LowSleep s1 = new LowSleep("大羊", date);
		System.out.println(s1);
		System.out.println(s1.getNameString());
		System.out.println(s1.getBirthday());
		date.setTime(132432432423L);//修改时间
		System.out.println(s1.getBirthday());		
		System.out.println("------------");
		LowSleep s2 = (LowSleep) s1.clone();//浅克隆
		System.out.println(s2);
		System.out.println(s2.getNameString());
		System.out.println(s2.getBirthday());
		System.out.println("------------");
		s2.setNameString("小羊");
		System.out.println(s2.getNameString());
		/*********区别:浅克隆************/
		date.setTime(1000L);//s1 s2 一起修改
		System.out.println(s1.getBirthday());	
		System.out.println(s2.getBirthday());
		/*********************/
		s2.setBirthday(new Date(2314324324324L));//只修改了s2
		System.out.println(s1.getBirthday());	
		System.out.println(s2.getBirthday());
		
		s1.setNameString("巨羊");
		System.out.println(s1.getNameString());
		System.out.println(s2.getNameString());
	}
}


2、深克隆

package com.lgd.prototype;

import java.util.Date;

public class DeepSleep implements Cloneable{
	private String nameString;
	private Date birthday;
	public DeepSleep() {
		// TODO Auto-generated constructor stub
	}
	
	public DeepSleep(String nameString, Date birthday) {
		super();
		this.nameString = nameString;
		this.birthday = birthday;
	}

	@Override
	protected Object clone() throws CloneNotSupportedException {
		Object object = super.clone(); //直接调用object对象的clone()方法
		
		//添加如下代码实现深复制
		DeepSleep s = (DeepSleep) object;
		s.birthday = (Date) this.birthday.clone();//将属性也进行克隆
		
		
		return object;
	}

	public String getNameString() {
		return nameString;
	}

	public void setNameString(String nameString) {
		this.nameString = nameString;
	}

	public Date getBirthday() {
		return birthday;
	}

	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}
}


package com.lgd.prototype;

import java.sql.Date;

public class ClientDeepcopy {
	public static void main(String[] args) throws CloneNotSupportedException {
		Date date = new Date(12324354543543L);
		DeepSleep s1 = new DeepSleep("大羊", date);
		System.out.println(s1);
		System.out.println(s1.getNameString());
		System.out.println(s1.getBirthday());
		date.setTime(132432432423L);//修改时间
		System.out.println(s1.getBirthday());		
		System.out.println("------------");
		DeepSleep s2 = (DeepSleep) s1.clone();//深克隆 s2对象的birthday是一个新对象。
		System.out.println(s2);
		System.out.println(s2.getNameString());
		System.out.println(s2.getBirthday());
		System.out.println("------------");
		s2.setNameString("小羊");
		System.out.println(s2.getNameString());
		/*********区别:深克隆************/
		date.setTime(1000L);//s1修改 ,s2不变
		System.out.println(s1.getBirthday());	
		System.out.println(s2.getBirthday());
		/*********************/
		s2.setBirthday(new Date(2314324324324L));//s1不变 ,s2修改
		System.out.println(s1.getBirthday());	
		System.out.println(s2.getBirthday());
		
		s1.setNameString("巨羊");
		System.out.println(s1.getNameString());
		System.out.println(s2.getNameString());
		
	}
}


3、利用序列化和反序列化实现深克隆

package com.lgd.prototype;

import java.io.Serializable;
import java.util.Date;

public class LowSleep implements Cloneable,Serializable{

	private static final long serialVersionUID = 1L;
	private String nameString;
	private Date birthday;
	public LowSleep() {
		// TODO Auto-generated constructor stub
	}
	
	public LowSleep(String nameString, Date birthday) {
		super();
		this.nameString = nameString;
		this.birthday = birthday;
	}

	@Override
	protected Object clone() throws CloneNotSupportedException {
		Object object = super.clone(); //直接调用object对象的clone()方法
		return object;
	}

	public String getNameString() {
		return nameString;
	}

	public void setNameString(String nameString) {
		this.nameString = nameString;
	}

	public Date getBirthday() {
		return birthday;
	}

	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}
}


package com.lgd.prototype;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.sql.Date;

/**
 * 测试原型模式(利用序列化与反序列化实现深克隆)
 * @author Administrator
 */
public class ClientSerializable {
	public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException {
		Date date = new Date(12324354543543L);
		LowSleep s1 = new LowSleep("大羊", date);
		System.out.println(s1);
		System.out.println(s1.getNameString());
		System.out.println(s1.getBirthday());
		
		//LowSleep s2 = (LowSleep) s1.clone();//浅克隆
		
		//使用序列化与反序列化实现深复制
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		ObjectOutputStream oos = new ObjectOutputStream(bos);
		oos.writeObject(s1);
		byte[] bytes = bos.toByteArray();
		
		ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
		ObjectInputStream ois = new ObjectInputStream(bis);
		LowSleep s2 = (LowSleep) ois.readObject();
		
		
		System.out.println("------------");		
		s2.setNameString("小羊");
		System.out.println(s2);
		System.out.println(s2.getNameString());
		System.out.println(s2.getBirthday());
		
		System.out.println("------------");		
		/*********区别:序列与反序列化************/
		date.setTime(1000L);
		System.out.println(s1.getBirthday());	
		System.out.println(s2.getBirthday());
		/*********************/

	}
}


4、测试

package com.lgd.prototype;

/**
 * 测试普通new方式创建对象和clone方式创建对象的效率差异
 * 如果需要短时间创建大量对象,并且new比较耗时,则可以考虑原型模式。
 * @author liguodong
 *
 */
public class ClientTest {
	
	public static void testNew(int size)
	{
		long start = System.currentTimeMillis();
		for(int i=0;i<size;i++)
		{
			Laptop t = new Laptop();
		}
		long end = System.currentTimeMillis();
		System.out.println("new创建的时间:"+(end-start));
	}
	public static void testClone(int size) throws CloneNotSupportedException
	{
		long start = System.currentTimeMillis();
		Laptop t = new Laptop();
		for(int i=0;i<size;i++)
		{
			Laptop temp = (Laptop) t.clone();
		}
		long end = System.currentTimeMillis();
		System.out.println("clone创建的时间:"+(end-start));
	}
	public static void main(String[] args) throws CloneNotSupportedException {
		testNew(1000);
		testClone(1000);
	}
}

class Laptop implements Cloneable{
	public Laptop(){//笔记本电脑
		try{
			Thread.sleep(10);//模拟创建对象耗时的过程。
		}catch(InterruptedException e)
		{
			e.printStackTrace();
		}
	}

	@Override
	protected Object clone() throws CloneNotSupportedException {
		// TODO Auto-generated method stub
		return super.clone();
	}
	
	
	
}


运行结果:

new创建的时间:10358

clone创建的时间:10



原型模式很少单独出现,一般是和工厂模式一起出现,通过clone方法创建一个对象,然后由工厂模式搭配起来。

创建者模式(都是用来创建对象)

单例模式***

保证一个类只有一个实例,并且提供一个访问该实例的全局访问点。

工厂模式

简单工厂***

用来生产同一等级中的任意产品。(修改已有代码)

工厂方法

用来生产同一等级结构中的任意产品。

抽象工厂

用来增加产品族的全部产品。

建造者模式

分离了对象子组件的单独构造和装配。从而构造出复杂的对象。

原型模式***

通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: