ProtoType: 原型类,声明一个克隆自己的接口。
ConcreatePrototype: 具体的原型类,是实现克隆自己的操作。
Client: 让一个原型对象克隆自己,从而产生一个新的对象。对象的属性完全相同。
应用案例:
现在需要将一头绵羊克隆多个,绵羊要长的一模一样,请编写程序实现。
package com.exam.prototypecommon;
/**
*author:bingbing
*日期:2020年5月6日
*时间:下午11:15:36
*绵羊
*/
public class Sheep {
private String name;
private int age;
private String color;
public Sheep(String name,int age,String color) {
super();
this.name=name;
this.age=age;
this.color=color;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
@Override
public String toString() {
return "Sheep [name=" + name + ", age=" + age + ", color=" + color + "]";
}
}
测试类:
package com.exam.prototypecommon;
/**
*author:bingbing
*日期:2020年5月6日
*时间:下午11:18:33
*克隆绵羊
*/
public class Test {
public static void main(String[] args) {
Sheep sheep=new Sheep("多利",1,"白色");
Sheep sheep1=new Sheep(sheep.getName(),sheep.getAge(),sheep.getColor());
Sheep sheep2=new Sheep(sheep1.getName(),sheep1.getAge(),sheep1.getColor());
System.out.println("sheep:"+sheep);
System.out.println("sheep1:"+sheep1);
System.out.println("sheep2:"+sheep2);
}
}
注: 最终看的是属性,因此需要重写一下toString()方法。
打印结果:
sheep:Sheep [name=多利, age=1, color=白色]
sheep1:Sheep [name=多利, age=1, color=白色]
sheep2:Sheep [name=多利, age=1, color=白色]
浅拷贝介绍
1) 对于数据类型是基本类型的成员变量,将原型的对象属性,复制一份出来,给新的对象,相当于是值传递。
2) 对于数据类型是引用数据类型的成员变量,那么会进行引用传递,比如是成员变量是某个类的对象、数组等,也就是将该成员变量的引用值( 内存地址),复制一份出来给新的对象。实际上新克隆出来的对象的成员变量的引用和原对象的成员变量的引用都指向了同一个实例。在这种情况下,一个对象修改其成员变量,那么也会影响到另一个对象的该成员变量值,改变的是引用值。
3) 浅拷贝,默认使用的方法是clone()方法来实现。
4) 原对象需要实现Cloneable接口。
package com.exam.prototype.improve;
/**
*author:bingbing
*日期:2020年5月7日
*时间:上午6:31:44
*/
public class Sheep implements Cloneable{
private String name;
private int age;
private String color;
public Sheep(String name,int age,String color) {
super();
this.name=name;
this.age=age;
this.color=color;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
@Override
public String toString() {
return "Sheep [name=" + name + ", age=" + age + ", color=" + color + "]";
}
@SuppressWarnings("null")
@Override
protected Object clone() throws CloneNotSupportedException {
Sheep sheep1=null;
try {
sheep1=(Sheep)super.clone();
return sheep1;
}catch(Exception e) {
throw new RuntimeException(e.getMessage());
}
}
}
测试类:
package com.exam.prototype.improve;
import com.exam.prototype.improve.Sheep;
/**
*author:bingbing
*日期:2020年5月7日
*时间:上午6:37:05
*浅拷贝
*/
public class Test {
public static void main(String[] args) {
Sheep sheep=new Sheep("多利",1,"白色");
try {
System.out.println(sheep.clone());
System.out.println(sheep.clone());
System.out.println(sheep.clone());
System.out.println(sheep.clone());
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
打印结果:
Sheep [name=多利, age=1, color=白色]
Sheep [name=多利, age=1, color=白色]
Sheep [name=多利, age=1, color=白色]
Sheep [name=多利, age=1, color=白色]
深拷贝介绍
1) 复制对象的所有基本数据类型的成员变量值
public class DeepProtoType implements Serializable, Cloneable{
public String name;
public DeepCloneableTarget deepCloneableTarget;
public DeepProtoType() {
super();
}
//重写克隆方法
@Override
protected Object clone() throws CloneNotSupportedException {
Object deep = null;
deep = super.clone();
DeepProtoType deepProtoType = (DeepProtoType)deep;
deepProtoType.deepCloneableTarget = (DeepCloneableTarget)deepCloneableTarget.clone();
// TODO Auto-generated method stub
return deepProtoType;
}
//对象序列化的方式
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 copyObj = (DeepProtoType)ois.readObject();
return copyObj;
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
return null;
} finally {
try {
//关闭流
bos.close();
oos.close();
bis.close();
ois.close();
} catch (Exception e2) {
// TODO: handle exception
System.out.println(e2.getMessage());
}
}
}
}
public class DeepCloneableTarget implements Serializable, Cloneable {
/**
*
*/
private static final long serialVersionUID = 1L;
private String cloneName;
private String cloneClass;
public DeepCloneableTarget(String cloneName, String cloneClass) {
this.cloneName = cloneName;
this.cloneClass = cloneClass;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
测试类:
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
DeepProtoType p = new DeepProtoType();
p.name = "多利羊";
p.deepCloneableTarget = new DeepCloneableTarget("新的多利羊", "CloneSheep");
//重写克隆方式
DeepProtoType p2 = (DeepProtoType) p.clone();
System.out.println("p.name=" + p.name + "p.deepCloneableTarget=" + p.deepCloneableTarget.hashCode());
System.out.println("p2.name=" + p.name + "p2.deepCloneableTarget=" + p2.deepCloneableTarget.hashCode());
//对象序列化方式
DeepProtoType p3 = (DeepProtoType) p.deepClone();
System.out.println("p.name=" + p.name + "p.deepCloneableTarget=" + p.deepCloneableTarget.hashCode());
System.out.println("p3.name=" + p.name + "p3.deepCloneableTarget=" + p3.deepCloneableTarget.hashCode());
}
打印结果:
p.name=多利羊p.deepCloneableTarget=1829164700
p2.name=多利羊p2.deepCloneableTarget=2018699554
p.name=多利羊p.deepCloneableTarget=1829164700
p3.name=多利羊p3.deepCloneableTarget=2093631819
1. 创建新的对象比较复杂时,使用原型模式,可以一定大大减少代码量,并且能够提升效率。
2. 不用重新初始化对象,而是获取了对象运行时的状态。
3. 如果原对象发生变化,那么其它克隆的对象也会发生变化,无需修改代码。
4. 在使用深拷贝时,可能需要写很多复杂的代码。
5. 需要为每个类配备一个克隆方法,对已有的类进行改造时,需要修改其源代码,那么违背了OCP原则。