一. 简单类型
1.定义:
原型模式(Prototype模式)是指:用原型实例指定创建对象的种类,并且通过拷 贝这些原型,创建新的对象 2) 原型模式是一种创建型设计模式,允许一个对象再创建另外一个可定制的对象, 无需知道如何创建的细节 3) 工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建 的对象通过请求原型对象拷贝它们自己来实施创建,即 对象.clone()。
思路:Java中Object类是所有类的根类,Object类提供了一个clone()方法,该方法可以 将一个Java对象复制一份,但是需要实现clone的Java类必须要实现一个接口Cloneable, 该接口表示该类能够复制且具有复制的能力 => 原型模式。
2.代码:
public class Sheep implements Cloneable{
private String name;
private Integer age;
private String address;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Sheep{" +
"name='" + name + ''' +
", age=" + age +
", address='" + address + ''' +
'}';
}
public Sheep(String name, Integer age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public static void main(String[] args) throws CloneNotSupportedException {
Sheep sheep1 = new Sheep("tom", 1, "北京");
Sheep sheep2 = new Sheep(sheep1.getName(), sheep1.getAge(), sheep1.getAddress());
Sheep sheep3= (Sheep) sheep1.clone();
System.out.println(sheep1);
System.out.println(sheep2);
System.out.println(sheep3);
}
创建的三个对象属性均一致。
二、浅拷贝
1.定义:
对于数据类型是基本数据类型的成员变量,浅拷贝会直接进行值传递,也就是将 该属性值复制一份给新的对象。
对于数据类型是引用数据类型的成员变量,比如说成员变量是某个数组、某个类 的对象等,那么浅拷贝会进行引用传递,也就是只是将该成员变量的引用值(内 存地址)复制一份给新的对象。因为实际上两个对象的该成员变量都指向同一个 实例。在这种情况下,在一个对象中修改该成员变量会影响到另一个对象的该成 员变量值
2.代码:
public class Sheep implements Cloneable{
private String name;
private Sheep friend;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Sheep getFriend() {
return friend;
}
public void setFriend(Sheep friend) {
this.friend = friend;
}
@Override
public String toString() {
return "Sheep{" +
"name='" + name + ''' +
", friend=" + friend +
'}';
}
public Sheep(String name, Sheep friend) {
this.name = name;
this.friend = friend;
}
}
public static void main(String[] args) throws CloneNotSupportedException {
Sheep friend = new Sheep("朋友羊",null);
Sheep sheep1 = new Sheep("羊1", friend);
Sheep sheep2 = new Sheep("羊1", friend);
System.out.println(sheep1.hashCode()+" friend:"+sheep1.getFriend().hashCode());
System.out.println(sheep2.hashCode()+" friend:"+sheep2.getFriend().hashCode());
}
//356573597 friend:1735600054
//21685669 friend:1735600054
结论:假如成员变量为引用类型,不实现clone方法会直接应用地址拷贝,两个变量指向同一个地址。
三、深拷贝
1.定义:
复制对象的所有基本数据类型的成员变量值;为所有引用数据类型的成员变量申请存储空间,并复制每个引用数据类型成员变 量所引用的对象,直到该对象可达的所有对象。也就是说,对象进行深拷贝要对 整个对象进行拷贝
2.代码:
public class Sheep implements Cloneable, Serializable {
private String name;
private Address address;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public Sheep(String name, Address address) {
this.name = name;
this.address = address;
}
//克隆方法
@Override
protected Object clone() throws CloneNotSupportedException {
Sheep clone = (Sheep)super.clone();
//属性克隆下
clone.address=new Address();
return clone;
}
//反序列化方法
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);
Sheep copyObj = (Sheep)ois.readObject();
return copyObj;
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
try {
bos.close();
oos.close();
bis.close();
ois.close();
} catch (Exception e2) {
System.out.println(e2.getMessage());
}
}
}
}
public class Address implements Serializable, Cloneable {
/**
* 克隆目标属性
*/
private static final long serialVersionUID = 1L;
private String cloneName;
private String cloneClass;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public static void main(String[] args) throws CloneNotSupportedException {
Sheep sheep = new Sheep("1", new Address());
Sheep clone = (Sheep) sheep.clone();
Sheep deepClone = (Sheep) sheep.deepClone();
System.out.println("原型羊"+sheep.hashCode()+" "+sheep.getAddress().hashCode());
System.out.println("克隆羊"+clone.hashCode()+" "+clone.getAddress().hashCode());
System.out.println("序列化方式克隆羊"+deepClone.hashCode()+" "+deepClone.getAddress().hashCode());
}
//原型羊856419764 621009875
//克隆羊363771819 2065951873
//序列化方式克隆羊1791741888 1595428806
总结:
-
创建新的对象比较复杂时,可以利用原型模式简化对象的创建过程,同时也能够提 高效率
-
不用重新初始化对象,而是动态地获得对象运行时的状态
-
如果原始对象发生变化(增加或者减少属性,其它克隆对象的也会发生相应的变化, 无需修改代码
-
在实现深克隆的时候可能需要比较复杂的代码
-
缺点:需要为每一个类配备一个克隆方法,这对全新的类来说不是很难,但对已有 的类进行改造时,需要修改其源代码,违背了ocp原则,这点请同学们注意