设计模式之原型模式

一预备知识 1. 首先我们要知道 原型模式是设计模式中的创建型
2.要了解原型模式我们要了解java 中的深拷贝和浅拷贝
3. 定义:所谓原型模式,就是我们利用一个已有的对象,创建更多的相同类型的对象

疑问:这样创建和我们直接new有什么区别吗?
二 疑难解答 1. Java的浅拷贝 看下面的类(不是在编辑器上复制来的,不规范之处就那么地了)
class Book implements Clonable{
private int price;
private Author author;
public Book clone(){
Book book = null;
try {
book = (Book) super.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return book;
}
//一些get set 方法
}


class Author {
private String name;
private int age;
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;
}
}
可以看出Book类可以被克隆Author 类不能被克隆
现在我们创建一个实例
Book book1 = new Book();
【设计模式之原型模式】book1.setPrice(1);
Anthor author = new Author();
author.setXXX();
book1.setAuthor(author);


这里我们就把Book的属性的值都初始化完,
接下来我们对这个实例进行克隆
Book book2 = book1.clone();
这时候book2.getPrice() = book1.getPrice();
但是book1==book2 的值为false因为在虚拟机堆中产生了两个实例,这两个引用指向的不是同一个对象。但是我们确把类Book的类型,属性值都拷贝过来了,这样和我们直接new Book相比,我们少了一些给新创建的对象赋值的操作,
注意我们上述复制称为浅复制,因为Book类有两个属性 price与Author
price是基本数据类型,所以我们的克隆来的对象中的price 也是新产生的int类型
而Author 是引用类型的对象,我们克隆的对象,只会产生一个指向原来的Author对象的引用,而不会重新在堆中创建一个实例(深复制与浅复制的区别就在这)
深复制中 引用类型的属性也就是Author,会在堆中又创建一个实例也就是下面的代码
Book中的浅复制
book1.getPrice() == book2.getPrice(); //结果为true
book1.getAuthor() == book2.getAuthor(); //结果为true
上面的复制过程中
内存中会有两个int大小的空间被占用,只有一个Author类型的空间会被占用
换句话说就是book1 中的 author = new Anthor();
book2 中 author = book1.author;
2. java中的深拷贝 Java中的深拷贝是通过序列化与反序列化来实现的。
还是上面的例子:
Book 与Author 都需要实现serializable接口
class Book implements Serializable{
private int price;
private Author author;


public Book deepClone() throws IOException, ClassNotFoundException{
// 写入当前对象的二进制流
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);


// 读出二进制流产生的新对象
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return (Book) ois.readObject();
}
//一些get set 方法
}
Author仅仅是实现序列化接口 这里不写了


然后Book bk1 = new Book();
Book bk2 = bk1.deepClone();
这就是深复制 这里会复制一个Book的实例,同时Author类也会重现创建一个实例,
3. 原型模式 了解了Java中的深浅拷贝,我们就可以很容易理解原型模式了
换句话说Java中的深浅拷贝就是原型模式
我们回过头来看定义就是我们利用一个已有的对象,创建更多的相同类型的对象
上述例子中Book 就是一个已知类型,我们通过克隆,创建了许多该对象的实例
同我们直接 new 相比我们省略了给他复制初始化的过程,简化了我们的开发,


4. 原型模式的有点与缺点 优点:1. 可以隐藏创建新对象的复杂性(这句话也说明 原型模式适合那些创建很复杂的对象,也适用与那些创建开销很大的对象)
2. 在某些环境下,复制比创建高效
3. 可扩展性好,依赖的是抽象
缺点:1.假设Author类中还有别的许多类,他们都要序列化,这就很麻烦
2.要为每一个类实现clone方法,对于已经存在的类,就很烦违反了开闭原则


5. 原型模式结构

1.0 原型模式需要接口
interface YX{
public Object clone();
}
2.0需要复制的类要实现这个接口 方法
class Book implements YX{
public Object clone(){
//实现
}


}
3.0 可以有多个实现,
4.0 原型模式的创建方式有两种:1简单型2管理型简单型就是上面的例子
管理型就是新建一个类 用map来记录都创建了那些对象:map.set("对象1",book1)
下面是完整的浅克隆的例子
package com.jd.test;
//演示浅克隆
public class Bookimplements Cloneable {
private int price;
private int size;
public Book clone(){
Book bk =null;
try {
bk = (Book)super.clone();
}catch (CloneNotSupportedException e){
}
return bk;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
@Override
public String toString(){
return "Book.price = "+this.getPrice()+"Book.size = "+this.getSize();
}
}
下面是主函数
package com.jd.test;
public class Main {
public static void main(String[] args) {
//浅克隆
Book b =new Book();
b.setPrice(1);
b.setSize(12);
System.out.println(b);
Book a = b.clone();
System.out.println(a);
}
}


下面是结果:
Book.price = 1Book.size = 12
Book.price = 1Book.size = 12
Process finished with exit code 0

    推荐阅读