设计模式之原型模式(java代码实现)
简述原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式是实现了一个原型接口(在java中实现Cloneable),,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。如,一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆
简述
原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式是实现了一个原型接口(在java中实现Cloneable),,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。如,一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用。还有在spring中的bean的scope中就有使用到原型模式。
原型模式的定义:用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。在这里,原型实例指定了要创建的对象的种类。用这种方式创建对象非常高效,根本无须知道对象创建的细节。
原型模式的优点:
- java自带的原型模式基于内存二进制流的复制,在性能上比直接 new 一个对象更加优良。
- 可以使用深克隆保存对象的状态,使用原型模式将对象复制一份,并将其状态保存起来,简化了创建对象的过程,以便在需要的时候使用。
原型模式的缺点:
- 在java中需要为每一个类都配置一个 clone 方法
- clone 方法位于类的内部,当对已有类进行改造的时候,需要修改代码,违反了开闭原则。
- 当实现深克隆时,需要编写较为复杂的代码,而且当对象之间存在多重嵌套引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来较麻烦(可以使用序列化和反序列化方式)。
原型模式的结构
原型模式包含以下主要角色。
- 抽象原型类:规定了具体原型对象必须实现的接口。
- 具体原型类:实现抽象原型类的 clone() 方法,它是被复制的对象。
- 访问类:使用具体原型类中的 clone() 方法来复制新的对象。
原型模式的克隆分为浅克隆和深克隆。
- 浅克隆:创建一个新对象,新对象的属性和原来对象一样,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。
- 深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。
uml类图
代码示例:
原型类代码 重点是实现Cloneable接口以及重写clone方法
package com.tianye.designModel.impl;
import java.io.*;
/**
* @author 田野上的风筝
* @version V1.0
* @Description: TODO
* @date 2020/12/2 10:37
*/
public class Prototype implements Cloneable, Serializable {
private String name;
private int age;
private RefObject refObject;
public Prototype(String name, int age) {
this.name = name;
this.age = age;
}
public RefObject getRefObject() {
return refObject;
}
public void setRefObject(RefObject refObject) {
this.refObject = refObject;
}
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;
}
//重写克隆方法 默认浅拷贝
@Override
protected Object clone() throws CloneNotSupportedException {
Prototype clone = (Prototype) super.clone();
return clone;
}
@Override
public String toString() {
return "Prototype{" +
"name='" + name + '\'' +
", age=" + age +
", refObject=" + refObject +
'}';
}
}
客户端 main方法 使用
public static void main(String[] args) throws CloneNotSupportedException {
Prototype prototype = new Prototype("原型模板",2);
prototype.setRefObject(new RefObject());
Prototype clone1 = (Prototype) prototype.clone();
Prototype clone2 = (Prototype) prototype.clone();
System.out.println(clone1);
System.out.println(clone2);
System.out.println("原型 hashCode"+prototype.getRefObject().hashCode());
System.out.println("浅克隆 hashCode"+clone1.getRefObject().hashCode());
System.out.println("浅克隆 hashCode"+clone2.getRefObject().hashCode());
System.out.println(prototype.getRefObject()==clone1.getRefObject());
System.out.println(prototype.getRefObject()==clone2.getRefObject());
}
运行mian方法,效果
上面使用的是浅克隆模式,下面使用深克隆模式,修改Prototype的clone方法
//深拷贝 利用反序列 和序列化
@Override
protected Object clone() {
//序列化 将当前对象序列化到内存中
ByteArrayOutputStream byteArrayOutputStream;
ObjectOutputStream oos = null;
ObjectInputStream ois = null;
try {
byteArrayOutputStream = new ByteArrayOutputStream();
oos = new ObjectOutputStream(byteArrayOutputStream);
oos.writeObject(this);
//反序列化
byte[] bytes = byteArrayOutputStream.toByteArray();
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
ois = new ObjectInputStream(bis);
return ois.readObject();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
} finally {
if (oos != null) {
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (ois != null) {
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
运行效果
更多推荐
所有评论(0)