原型模式

为什么引入原型模式?

当我们需要创建某个对象的时候,我们使用new关键字,但是当我们需要创建两个相同的对象,接着new,当数量特定少的时候,我们可以采用直接创建对象,但是当我们需要创建很多对象的时候,我们就不能一直new,首先是因为堆内存有限,只允许我们new特定数量的对象,因此我们需要另一种方式,快速的实现对象的复制,克隆,因此引入原型模式。

原型模式是什么?

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

核心思想:

原型模式的实现方式十分简单,即只需继承Cloneable接口,覆盖clone()方法。

这里需要解释一下什么是浅克隆和深克隆。

浅克隆:

继承Cloneable接口,覆盖clone方法所实现的克隆就是浅克隆,浅克隆的方式即Object类的clone方法只是拷贝对象本身,其对象内部的数组,引用对象都不拷贝,还是指向原生对象的内部元素地址,int,long,char等基恩类型会被拷贝,但是String类型,通过字符串常量池在需要的时候才在内存中创建新的字符串,读者可以把String当做基本类型使用即可。

深克隆:

将对象的所有东西都拷贝一份,实现对象之间的独立。深拷贝在浅拷贝的基础上,对数组,引用对象单独拷贝。

具体案例:

我们现在有一个名牌汽车,我们希望在以这件车为模型生产很多辆

代码:

package com.dong.yuanxing;

import java.util.ArrayList;

public class Car implements Cloneable{
	private String name;
	private int Id;
	private ArrayList<String> otherDes = new ArrayList<String>() ;
	
	public Car clone() {
		Car car =null;
		try {
			car = (Car)super.clone();
		} catch (CloneNotSupportedException e) {
			System.out.println("克隆不支持");
			return null;
		}
		return car;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getId() {
		return Id;
	}
	public void setId(int id) {
		Id = id;
	}
	public ArrayList<String> getOtherDes() {
		return otherDes;
	}
	public void setOtherDes(String value) {
		this.otherDes.add(value);
	}
}

package com.dong.yuanxing;

import java.util.ArrayList;
//浅拷贝
public class Main {
	public static void main(String args[]) {
		Car carold ,carnew,carthre;
		carold = new Car();
		carold.setOtherDes("111");	
		carnew = carold.clone();	
		carnew.setOtherDes("222");
		System.out.println(carnew + carnew.getOtherDes().toString());	
	}
}

深拷贝需要改动的地方:

	public Car clone() {
		Car car =null;
		try {
			//浅拷贝
			car = (Car)super.clone();
			//深拷贝,即对私有的类变量进行单独的拷贝。
			//car = (Car)super.clone();
			//car.otherDes = (ArrayList<String>) this.otherDes.clone();
		} catch (CloneNotSupportedException e) {
			System.out.println("克隆不支持");
			return null;
		}
		return car;
	}


	public static void main(String args[]) {
		Car carold ,carnew;
		carold = new Car();
		carold.setOtherDes("111");	
		carnew = carold.clone();	
		carnew.setOtherDes("222");
		System.out.println(carold + carold.getOtherDes().toString());
		System.out.println(carnew + carnew.getOtherDes().toString());
	}

优点

拷贝的性能优良,原型模式是在内存二进制流的拷贝,要比直接new一个对象的性能好。

缺点

浅拷贝不能拷贝对象的所有,对于内部的数组,引用对象是不会拷贝的,需要使用深拷贝。

扩展:

深拷贝的另一种实现方式:

package com.dong.prototype;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class DeepCloneObj implements Serializable{

	private static final long serialVersionUID = 1L;
	//为需要克隆的类
	private StudentA student;
	public StudentA getStudent() {
		return student;
	}
	public void setStudent(StudentA student) {
		this.student = student;
	}
	public DeepCloneObj clone() {
		ByteArrayOutputStream bos;
		ObjectOutputStream oos;
			try {
				bos = new ByteArrayOutputStream();
				oos = new ObjectOutputStream(bos);
				oos.writeObject(this);
				ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
				ObjectInputStream ois = new ObjectInputStream(bis);
				try {
					return (DeepCloneObj) ois.readObject();
				} catch (ClassNotFoundException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		return null;			
	}
}