前篇——软件设计模式-基础
前篇——软件设计模式-三种工厂模式
前篇——软件设计模式-装饰者模式
前篇——软件设计模式-单例模式
原型模式属于创建型模式
克隆:复制和拷贝,即从原型中产生出同样的复制品,其外表以及遗传基因与原型完全相同,但大多行为思想不同。
定义:用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象
原型模式的结构中包含两种角色:
(别骗自己了,就是忘了或者不会(淦))
Object类型是所有引用类型的基础类,在引用类型的顶端。
它的引用变量可以指向任何类型的一个对象
super用于在子类中指代父类的对象
super使用三种情况:
cloneable其实就是一个标记接口(空接口),只有实现这个接口后,然后在类中重写Object中的clone方法,然后通过类调用clone方法才能克隆成功,如果不实现这个接口,则会抛CloneNotSupportedException(克隆不被支持)异常。这段话来自“漫步夕阳下”的博客
tip:finally 关键字:无论是否发生异常,代码总被执行
一般我们做异常处理通过三种:
try{
//程序代码
}catch(ExceptionName e1){
//catch块
}
简单了解克隆的方式:
//抽象原型(Prototype)
public interface Prototype{
//抛出克隆不支持的异常
public Object clone() throws CloneNotSupportedException;
}
//具体原型()立方体类
public class Cubic implements Prototype,Cloneable{
//长宽高
double length,width,height;
//构造方法赋值
public Cubic(douible length,double width,double height){
this.length = length;
this.width = width;
this.height = height;
}
//实现抽象原型接口的克隆方法
public Object clone() throws CloneNotSupportedException{
Object obj = super.clone();
return obj;
}
}
//测试类
public class Test{
public static void main(String args[]){
Cubic c = new Cubic(10.0,9.0,8.0);
Cubic c1 = (Cubic)c.clone();
System.out.println("c1值"+c1.length+c1.width+c1.height);
}
}
浅克隆:不能做到完全克隆,如下面的例子,修改sheep1的日期,克隆的对象sheep2,也会更改,即两个对象同时使用一个date对象,一改都改,聚有耦合性。
import java.util.Date;
//Cloneable是个空接口,通过原型模式来创建对象,克隆方法不是原型中的方法,是Object类中的方法
public class Sheep implements Cloneable{
private String name;
private Date birthday;
//构造方法赋值
public Sheep(String name,Date birthday){
this.sname = sname;
this.birthday = birthday;
}
//重写Object类中的克隆方法
public Object clone()throws CloneNotSupportedException{
Object obj = super.clone();
return obj;
}
//一些get、set方法
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
public void setBirthday(Date birthday){
this,birthday = birthday;
}
public Date getbirthday(){
return birthday;
}
}
//测试类
public class test{
public static void main(String args[]){
Date date1 = new Date(12312312);
Sheep sheep1 = new Sheep("多莉",date1);
//显示sheep1的信息
System.out.println(sheep1+"--"+sheep1.getSname()+"--"+sheep1.getbirthday());
Sheep sheep2 = (Sheep)sheep1.clone();
//显示sheep2的信息
System.out.println(sheep2+"--"+sheep2.getSname()+"--"+sheep2.getbirthday());
//判断是否是同一个对象
System.out.println(sheep1 == sheep2);
//修改sheep1的信息
sheep1.getBirthday().setYear(2020);
sheep1.setName("布莱克");
//判断修改sheep1的日期,sheep2的日期是否会改变
System.out.println(sheep1.getBirthday()==sheep2.getbirthday());
}
}
深克隆,即被克隆对象与克隆对象基本无任何关系。改原型中的任何属性都不会影响新克隆的对象。(降低耦合性)
从浅克隆修改:
克隆对象的同时也克隆其属性。
实现:(修改e.g.2种的clone()方法即可):
public Object clone() throws CloneNotSupportedException{
Object obj = super.clone();
Sheep p = (Sheep)obj;
p.birthday = (Date)this.birthday.clone();
return obj;
}
所谓序列化和反序列化
就是将对象读到字节数组输出流中,在把它读出来。
在2.2.2.1种我们实现例二的深克隆是通过,修改clone方法来实现的,用序列化的放法,我们只需要在测试类种修改即可。
:(序列化、反序列化实现:
public class test1{
public static void main(String args[]){
Date d1 = new Date(12121221);
Sheep sheep3 = new Sheep("莱弗利",d1);
System.out.println("这是原型对象sheep3--"+sheep3+"--"+sheep3.name+"--"+sheep3.birthday);
/*
为了实现深克隆,不直接克隆
Sheep sheep2 = (Sheep)sheep1.clone();
*/
//序列化过程:
//声明一个字节数组输出流(对象),通过ByteOutputStream
ByteArrayOutputStream bos = new ByteArrayOutputStream();
//包装一下对象(对象输入流(ObjectOutputStream))
ObjectOutputStream oos = new ObjectOutputStream(bos);
oss.writeObject(sheep3);
byte[] bytes = bos.toByteArray();
//反序列化过程(把写入字节数组输出流的对象再读出来):
//通过ByteArrayInputStream
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bis);
//读出来是Object类型,强转成Sheep,得到对象sheep4
Sheep sheep4 = (Sheep)ois.readObject(sheep3);
System.out.println("这是克隆出的sheep4对象--"+sheep4+"--"+sheep4.name+"--"+sheep4.birthday);
}
}
此时,再次修改sheep3,对sheep4无任何影响。
因为用到序列化,所以说我们需要导入java的io包,以及让具体原型(Sheep)除了实现Cloneable接口,还要实现一个序列化的接口(Serializable)
即
import java.io.*;
public class Sheep implements Cloneable,Serializable{
/*
内部就省略了,均是在e.g.2中做出一点修改。
*/
}
复制的对象,所有的变量都含有原来对象相同的值,而所有的对其他对象的引用,仍然指向原来的对象。
而深克隆把引用的变量指向复制过的新的对象,而不是原有的被引用的对象。其实浅克隆的基本数据类型是自动进行深克隆的(值的复制)
浅克隆转化为深克隆: