原型模式
为什么引入原型模式?
当我们需要创建某个对象的时候,我们使用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;
}
}