1996年7月5日,英国科学家伊恩·威尔穆特博士成功的克隆出了一只小羊,小羊与它的“母亲”一模一样。这只小羊的名字就是Dolly。
Dolly是由……
不要认为介绍多莉克隆的故事和本文牛头不对马嘴,事实上多少还是有点关系的。
上一篇:建造者模式
1.什么是原型模式?
原型模式就是用来创建重复的对象,再直白一点:复制粘贴的原理。
怎么样?是不是和克隆羊是不是还能扯上关系?
现在假如有个对象的创建过程及其复杂,可能需要代码一万行(此处使用了夸张的手法……),那如果你需要再创建一个这样的对象,是不是还需要来一万行代码?
为了解决这种问题,出现了原型模式,也就是有一个对象作为模板,再复制出一个新的对象。
2.如何使用原型模式?
案例:就拿正版书和盗版书为例:
1)定义正版书类
注意:原型类需要实现Cloneable
接口。
/**
* 定义原型类(正版书)
*/
public class Book implements Cloneable {
/**
* 书名
*/
private String name;
/**
* 作者
*/
private String author;
/**
* 出版时间
*/
private Date date;
/**
* 重写clone方法(ctrl+O)
* 一:浅克隆
*/
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
/**
* 重写to String方法
*/
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", author='" + author + '\'' +
", date=" + date +
'}';
}
/**
* 重写构造方法
*/
public Book(String name, String author, Date date) {
this.name = name;
this.author = author;
this.date = date;
}
}
/**
* set方法
*/
public void setName(String name) {
this.name = name;
}
public void setAuthor(String author) {
this.author = author;
}
public void setDate(Date date) {
this.date = date;
}
2)定义测试类
/**
* 定义测试类
*/
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Date date = new Date();
//1.new一个正版书类
Book book = new Book("好好学java","张三",date);
//2.通过正版书进行clone,得到盗版书
Book piracyBook = (Book) book.clone();
//输出正版书信息
System.out.println(book);
//为了区分两本书,输出hashCode
System.out.println("正版书的hashCode:"+book.hashCode());
System.out.println("==================");
//输出盗版书信息
System.out.println(piracyBook);
//为了区分两本书,输出hashCode
System.out.println("盗版书的hashCode:"+piracyBook.hashCode());
System.out.println("==================");
//改变原型(book)对象的值
date.setTime(121212121);
System.out.println(book);
System.out.println(piracyBook);
}
}
3)测试结果
原型模式到这里你以为就Over
了?不知道你有没有发现:如果Book
对象的某个参数一变,则piracyBook
对象的参数也会随之改变,这种clone
我们称之为浅克隆
既然有浅克隆
,那肯定也有深克隆
嘛。那到底什么是深克隆?
拿上面的案例来说,当我们的正版书的某个参数改变了之后,让以他为原型克隆的其他盗版书的参数依然保持第一次克隆时候的值。(比如:上面的正版书的author
参数的值变为李四了,但是盗版书的author
依然保持为张三,这就是深克隆)。
3.如何实现深克隆?
我们可以通过序列化和反序列化
或者是通过重写clone()方法
来进行深克隆。
3.1重写clone()方法
1)修改clone()方法
在上面案例中的第一步:定义正版书(Book)类
的时候,对clone()
方法进行改写。
/**
* 重写clone方法(ctrl+O) 二:深克隆
*/
@Override
protected Object clone() throws CloneNotSupportedException {
//获取book对象
Book book = (Book) super.clone();
//将对象的引用也clone一份并赋值
book.date = (Date) this.date.clone();
return book;
}
2)重新跑一下测试类
我们发现,两个对象依然不是同一个对象,当date
参数的值被改变之后,也只是book
正版书对象的date
值变了,而piracyBook
的值却依然保持第一次复制出来的值。
3.2 序列化和反序列化
1)Book类实现Serializable接口
2)修改测试类
public class Test {
public static void main(String[] args) throws Exception {
Date date = new Date();
Book book = new Book("三国演义", "罗贯中", date);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(book);
byte[] bytes = bos.toByteArray();
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bis);
Book piracyBook = (Book) ois.readObject();
System.out.println("正版书book:" + book);
System.out.println("盗版书piracyBook:" + piracyBook);
System.out.println("===================");
//修改date的值,看盗版书的date值会不会随之改变
date.setTime(123123123141L);
System.out.println("正版书book:" + book);
System.out.println("盗版书piracyBook:" + piracyBook);
}
}
3)测试结果
所以使用序列化和反序列化需要使用IO流
交互,操作起来比较麻烦,如果需要使用深克隆
,我们一般会选择使用重写clone()方法
的方式来实现
4.浅克隆和深克隆的区别?
1)浅克隆:
对值类型的成员变量进行值的复制,对引用类型的成员变量只复制引用,不复制引用的对象。
2)深克隆:
对值类型的成员变量进行值的复制,对引用类型的成员变量也进行引用对象的复制。至此,23中设计模式中的第一种类型:创建型模式
就写完了,下面写第二种类型:结构型模式