《Head First 设计模式》笔记23-原型模式
定义
原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
浅拷贝:使用一个已知实例对新创建实例的成员变量逐个赋值,这个方式被称为浅拷贝。
深拷贝:当一个类的拷贝构造方法,不仅要复制对象的所有非引用成员变量值,还要为引用类型的成员变量创建新的实例,并且初始化为形式参数实例值。
模式结构
原型模式主要包含如下三个角色:
- Prototype:抽象原型类。声明克隆自身的接口。
- ConcretePrototype:具体原型类。实现克隆的具体操作。
- Client:客户类。让一个原型克隆自身,从而获得一个新的对象。
所有的 Java 类都继承至 Object,而 Object 类提供了一个 clone() 方法,该方法可以将一个 java 对象复制一份,因此在 java 中可以直接使用 clone() 方法来复制一个对象。但是需要实现 clone 的 Java 类必须要实现一个接口: Cloneable. 该接口表示该类能够复制且具体复制的能力,如果不实现该接口而直接调用 clone() 方法会抛出 CloneNotSupportedException 异常。如下:
public class PrototypeDemo implements Cloneable{
public Object clone(){
Object object = null;
try {
object = super.clone();
} catch (CloneNotSupportedException exception) {
System.err.println("Not support cloneable");
}
return object;
}
//……
}
Java 中任何实现了 Cloneable 接口的类都可以通过调用 clone() 方法来复制一份自身然后传给调用者。一般而言,clone() 方法满足:
- 对任何的对象 x,都有 x.clone() !=x,即克隆对象与原对象不是同一个对象。
- 对任何的对象 x,都有 x.clone().getClass()==x.getClass(),即克隆对象与原对象的类型一样。
- 如果对象 x 的 equals() 方法定义恰当,那么 x.clone().equals(x) 应该成立。
模式实现
简历:Resume.java
public class Resume implements Cloneable {
private String name;
private File file;
/**
* 构造函数:初始化简历
*/
public Resume(String name, File file){
this.name = name;
this.file = file;
}
/**
* 克隆该实例
*/
public Object clone() {
Resume resume = null;
try {
resume = (Resume) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return resume;
}
public void display(){
System.out.println("简历名:" + name + ",简历文件:" + file);
}
}
客户端: Client.java
public class Client {
public static void main(String[] args) {
//原型A对象
Resume a = new Resume("小李子", "1.pdf");
//克隆B对象
Resume b = (Resume) a.clone();
//输出A和B对象
System.out.println("----------------A--------------");
a.display();
System.out.println("----------------B--------------");
b.display();
}
}
打印结果:A,B相同,因为 clone() 是浅复制。
修改 clone() 方法
public Object clone() {
Resume resume = null;
try {
resume = (Resume) super.clone();
resume.field = this.field.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return resume;
}
这样如果字段很多,会比较麻烦。所以可以使用序列化。
/* 深复制 */
public Object 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 ois.readObject();
}
优缺点
优点
- 如果创建新的对象比较复杂时,可以利用原型模式简化对象的创建过程,同时也能够提高效率。
- 可以使用深克隆保持对象的状态。
- 原型模式提供了简化的创建结构。
缺点
- 在实现深克隆的时候可能需要比较复杂的代码。
- 需要为每一个类配备一个克隆方法,而且这个克隆方法需要对类的功能进行通盘考虑,这对全新的类来说不是很难,但对已有的类进行改造时,不一定是件容易的事,必须修改其源代码,违背了 “开闭原则”。
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 bin07280@qq.com
文章标题:《Head First 设计模式》笔记23-原型模式
文章字数:945
本文作者:Bin
发布时间:2018-08-05, 16:35:17
最后更新:2019-08-06, 00:07:35
原始链接:http://coolview.github.io/2018/08/05/Head-First-%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/%E3%80%8AHead-First-%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E3%80%8B%E7%AC%94%E8%AE%B023-%E5%8E%9F%E5%9E%8B%E6%A8%A1%E5%BC%8F/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。