一、背景
原型模式具体怎么使用,下面我会详细讲,如果有那个地方讲的不到位了,请大家多多指教,共同学习,我尽量以白话的形式进行展示,废话不多说了,下面开始。
二、简单的原型设计模式
1.先来理解一个简单的原型模式的设计吧(原型对象Prototype.java)
public class Prototype implements Cloneable {
protected Object clone()throws CloneNotSupportedException{
return super.clone();
}
}
public class ConcretePrototype extends Prototype {
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
2.测试类
public class CloneTest {
public static void main(String[] args) {
ConcretePrototype cp = new ConcretePrototype();
cp.setAge(18);
try {
ConcretePrototype copy = (ConcretePrototype) cp.clone();
System.out.println(copy.getAge());
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
运行上面的代码,结果是:18
总结:一般我们来讲,要想创建两个不同的对象,需要的是调用一个类的构造方法的,是clone(克隆)复制的是字节码文件,创建出来的对象,不经过类的构造方法。这个就是我们的原型设计模式,但是这样写代码的话,可扩展性就不是那么好了,这个怎么讲呢,就是说,我们的类中如果有上百个属性,再这么写确实就不太好了,其实这正是原型模式什么时候用的时机,下面就讲讲具体的程序可扩展性。
三、概念以及支持的范围
1.对于能够直接拷贝其实际内容的数据类型/只支持9种,八大基本类型+String类型,这就是浅克隆。如果一个类中有不属于这几种类型的,或者更加复杂的类型,这时候我们可能就要用到了深克隆了。
2.浅克隆:仅仅克隆基本类型变量,而不克隆引用类型的变量。
深克隆:既克隆基本类型变量,也克隆引用类型变量。
四、可扩展性的原型模式(不是最佳的)
1.这个也不符合,我只是贴出来和下面的作对比,不然你们看着就很懵逼了。
public class Monkey {
//身高
protected int height;
//体重
protected int weight;
//生日
protected Date birthday; //不是基本类型
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
public class GoldRingedStaff implements Serializable {
private float height = 100;//长度
private float diameter = 10;//直径
//金箍棒长大
public void grow(){
this.diameter *= 2;
this.height *=2;
}
//金箍棒缩小
public void shrink(){
this.diameter /=2;
this.height /=2;
}
}
//齐天大圣
public class TheGreatestSage extends Monkey implements Cloneable,Serializable {
//金箍棒
private GoldRingedStaff staff;
//出生就有金箍棒了
public TheGreatestSage(){
this.staff = new GoldRingedStaff();
this.birthday = new Date();
this.height = 150;
this.weight = 30;
}
public GoldRingedStaff getStaff() {
return staff;
}
public void setStaff(GoldRingedStaff staff) {
this.staff = staff;
}
//72变化 用clone,分身
public Object clone(){
try {
return super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
return null;
}
}
//分身技能
public void change(){
TheGreatestSage copySage = (TheGreatestSage) clone();
System.out.println("大圣本身的生日:"+this.getBirthday().getTime());
System.out.println("克隆大圣的生日:"+copySage.getBirthday().getTime());
System.out.println("大圣和克隆大圣是否是同一个对象:"+(this == copySage));
System.out.println("大圣和克隆大圣的金箍棒是否是同一个:"+(this.getStaff() == copySage.getStaff
()));
}
}
3.
public class TestPrototype {
public static void main(String[] args) {
TheGreatestSage sage = new TheGreatestSage();
sage.change();
}
}
结果:
大圣本身的生日:1555833518960
克隆大圣的生日:1555833518960
大圣和克隆大圣是否是同一个对象:false
大圣和克隆大圣的金箍棒是否是同一个:true
生日相同,金箍棒也相同,不符合要求啊,怎么办呢,这时候我们得修改代码,clone()方法重写。
五、最后贴一个最符合规定的
public class Monkey {
//身高
protected int height;
//体重
protected int weight;
//生日
protected Date birthday; //不是基本类型
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
public class GoldRingedStaff implements Serializable {
private float height = 100;//长度
private float diameter = 10;//直径
//金箍棒长大
public void grow(){
this.diameter *= 2;
this.height *=2;
}
//金箍棒缩小
public void shrink(){
this.diameter /=2;
this.height /=2;
}
}
//齐天大圣
public class TheGreatestSage extends Monkey implements Cloneable,Serializable {
//金箍棒
private GoldRingedStaff staff;
//出生就有金箍棒了
public TheGreatestSage(){
this.staff = new GoldRingedStaff();
this.birthday = new Date();
this.height = 150;
this.weight = 30;
}
public GoldRingedStaff getStaff() {
return staff;
}
public void setStaff(GoldRingedStaff staff) {
this.staff = staff;
}
//72变化 用clone,分身
public Object clone(){
ByteArrayOutputStream bos = null;
ObjectOutputStream oos = null;
ByteArrayInputStream bis = null;
ObjectInputStream ois = null;
try {
//return super.clone();
//修改代码
//序列化
bos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bos);
oos.writeObject(this);
//反序列化
bis = new ByteArrayInputStream(bos.toByteArray());
ois = new ObjectInputStream(bis);
TheGreatestSage copy = (TheGreatestSage) ois.readObject();
copy.birthday = new Date();
return copy;
} catch (Exception e) {
e.printStackTrace();
return null;
}finally {
try {
bos.close();
oos.close();
bis.close();
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//分身技能
public void change(){
TheGreatestSage copySage = (TheGreatestSage) clone();
System.out.println("大圣本身的生日:"+this.getBirthday().getTime());
System.out.println("克隆大圣的生日:"+copySage.getBirthday().getTime());
System.out.println("大圣和克隆大圣是否是同一个对象:"+(this == copySage));
System.out.println("大圣和克隆大圣的金箍棒是否是同一个:"+(this.getStaff() == copySage.getStaff()));
}
}
public class TestPrototype {
public static void main(String[] args) {
TheGreatestSage sage = new TheGreatestSage();
sage.change();
}
}
结果:
大圣本身的生日:1555835467763
克隆大圣的生日:1555835467863
大圣和克隆大圣是否是同一个对象:false
大圣和克隆大圣的金箍棒是否是同一个:false
这个就很符合现实了,你们可以跟上面的对比,看到底改动那个地方了。
六、结束
上面就是我对这个原型模式得理解,还需要在现实代码中磨练,共勉,如有不足请多多指教。
Always keep the faith!!!