原型模式
1.实际案例
克隆出10只相同的羊,要求属性完全相同
2.传统方式解决
public class Client {
public static void main(String[] args) {
Sheep sheep = new Sheep("tom",1,"白色");
Sheep sheep1 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
Sheep sheep2 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
Sheep sheep3 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
Sheep sheep4 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
Sheep sheep5 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
Sheep sheep6 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
System.out.println(sheep);
System.out.println(sheep1);
System.out.println(sheep2);
System.out.println(sheep3);
System.out.println(sheep4);
System.out.println(sheep5);
System.out.println(sheep6);
}
}
方式弊端:
- 在创建新的对象时,总是需要重新获取原始对象的属性,如果创建的对象比较复杂时,效率较低
- 总是要初始化对象,儿额不是动态的获得对象运行时的状态,不够灵活
改进的思路:
Java中Object是所有类的基类,提供了一个clone()方法,可以将java对象复制一份,但是需要实现Cloneable接口=》原型模式
3.原型模式的概念
- 用原型实例指定创建对象的种类,并且通过拷贝这些原型,创建新的对象
- 原型模式是一种创建型的设计模式,允许一个对象再创建另外一个可定制的对象,无需知道如何创建的细节
- 通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝他们字节来实施创建,即对象,clone()
4.原型模式实现(浅拷贝)
需要克隆的类实现Coneable接口,重写clone()方法,完成克隆,程序会拥有更高的扩展性
public class Sheep implements Cloneable {
private String name;
private int age;
private String color;
/**
* 克隆该实例,使用默认的克隆方法来完成
* @return
* @throws CloneNotSupportedException
*/
@Override
protected Object clone() throws CloneNotSupportedException {
Sheep sheep = null;
try {
sheep = (Sheep) super.clone();
}catch (Exception e){
System.out.println(e.getMessage());
}
return sheep;
}
}
这种方式是浅拷贝,当数据中有对象时,拷贝出的对象只是原对象指向的空间,没有创建出新的对象
5.原型模式(深拷贝)
存在的问题:
- 当对象中的成员变量是引用类型的,如一个类对象,当出现这样的情况时,进行浅拷贝就会出现,只能拿到该对想的存储地址的问题
所以我们需要进行深拷贝:
5.1 clone方法
/**
* 深拷贝
* 方式1:重写clone方法
*/
@Override
protected Object clone() throws CloneNotSupportedException {
Object deep = null;
//完成对基本数据类型的克隆
deep = super.clone();
//对引用类型的属性,进行单独处理
DeepProtoType deepProtoType = (DeepProtoType) deep;
deepProtoType.deepCloneableTarget = (DeepCloneableTarget) deepCloneableTarget.clone();
return deep;
}
5.2 反序列化
/**
* 深拷贝
* 方式二:序列化反序列化
* @return
*/
public Object deepClone(){
//创建流对象
ByteArrayOutputStream bos = null;
ObjectOutputStream oos = null;
ByteArrayInputStream bis = null;
ObjectInputStream ois = null;
try {
bos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bos);
//当前对象以对象流的形式输出
oos.writeObject(this);
//反序列化
bis = new ByteArrayInputStream(bos.toByteArray());
ois = new ObjectInputStream(bis);
DeepProtoType deep = (DeepProtoType) ois.readObject();
return deep;
}catch (Exception e){
e.printStackTrace();
return null;
}finally {
try {
bos.close();
oos.close();
bis.close();
ois.close();
}catch (Exception e){
e.printStackTrace();
}
}
}