一、定义
使用原型实例指定创建对象的种类,然后通过拷贝这些原型来创建新的对象
二、UML图
三、详情分析
原型模式中的关键角色有三个:
- 使用者;
- 原型;
- 新实例
使用者需要建立一个原型,才能基于原型拷贝出新实例
使用场景分析
- 资源优化场景。也就是当进行对象初始化需要使用很多外部资源时,比如,IO 资源、数据文件、CPU、网络和内存等
- 复杂的依赖场景。 比如,F 对象的创建依赖 A,A 又依赖 B,B 又依赖 C……于是创建过程是一连串对象的 get 和 set
- 性能和安全要求的场景。
比如,同一个用户在一个会话周期里,可能会反复登录平台或使用某些受限的功能,每一次访问请求都会访问授权服务器进行授权,但如果每次都通过
new 产生一个对象会非常烦琐,这时则可以使用原型模式 - 同一个对象可能被多个修改者使用的场景。
比如,一个商品对象需要提供给物流、会员、订单等多个服务访问,而且各个调用者可能都需要修改其值时,就可以考虑使用原型模式 - 需要保存原始对象状态的场景。 比如,记录历史操作的场景中,就可以通过原型模式快速保存记录
- 结合工厂模式来使用。 在实际项目中,原型模式除了单独基于对象使用外,还可以结合工厂方法模式一起使用,通过定义统一的复制接口,比如
clone、copy。使用一个工厂来统一进行拷贝和新对象创建, 然后由工厂方法提供给调用者使用
1. Clone分析
浅克隆
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.ToString;
@Data
@AllArgsConstructor
@ToString
public class Sheep implements Cloneable{
private String name;
private int age;
private String color;
/**
* 使用默认的clone方法来完成
* @return
* @throws CloneNotSupportedException
*/
@Override
protected Object clone() {
Sheep sheep = null;
try {
sheep = (Sheep) super.clone();
}catch (CloneNotSupportedException ex){
ex.printStackTrace();
}
return sheep;
}
}
// 简单测试
public class Client {
public static void main(String[] args) {
System.out.println("原型模式");
Sheep sheep = new Sheep("jack",2,"白色");
Sheep sheep2 = (Sheep) sheep.clone();
Sheep sheep3 = (Sheep) sheep.clone();
Sheep sheep4 = (Sheep) sheep.clone();
Sheep sheep5 = (Sheep) sheep.clone();
System.out.println(sheep);
System.out.println(sheep2);
System.out.println(sheep3);
System.out.println(sheep4);
System.out.println(sheep5);
}
}
原型模式
Sheep(name=jack, age=2, color=白色)
Sheep(name=jack, age=2, color=白色)
Sheep(name=jack, age=2, color=白色)
Sheep(name=jack, age=2, color=白色)
Sheep(name=jack, age=2, color=白色)
深克隆
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.io.ByteArrayOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
/**
* @Description 原型
*/
@Data
@NoArgsConstructor
public class DeepProtoType implements Serializable,Cloneable {
private static final long serialVersionUID = 7049613497521134388L;
private String name;
private DeepCloneableTarget deepCloneableTarget;
/**
* 深拷贝1 使用clone方法
*
* @return
* @throws CloneNotSupportedException
*/
@Override
protected Object clone() throws CloneNotSupportedException {
Object deep = null;
deep = super.clone();
// 对引用 类型的属性,DeepProtoType
DeepProtoType deepProtoType = (DeepProtoType) deep;
DeepCloneableTarget deepCloneableTarget1 = (DeepCloneableTarget)deepCloneableTarget.clone();
deepProtoType.setDeepCloneableTarget(deepCloneableTarget1);
return deepProtoType;
}
/**
* 序列化
*
* @return
*/
protected Object deepClone(){
// 创建流对象
ByteArrayOutputStream bos = null;
ByteArrayInputStream bis = null;
ObjectOutputStream oos = null;
ObjectInputStream ois = null;
DeepProtoType copyObj =null;
try {
// 序列化
bos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bos);
oos.writeObject(this); // 当前这个对象以对象流的方式输出
// 反序列化
bis = new ByteArrayInputStream(bos.toByteArray());
ois = new ObjectInputStream(bis);
copyObj = (DeepProtoType) ois.readObject();
}catch (Exception ex){
ex.printStackTrace();
} finally {
try {
bos.close();
bis.close();
oos.close();
ois.close();
}catch (Exception ex){}
}
return copyObj;
}
}
/**
* @Description
*/
public class DeepCloneableTarget implements Serializable,Cloneable {
private static final long serialVersionUID = -2854149381688693250L;
private String cloneName;
private String cloneClass;
public DeepCloneableTarget(String cloneName, String cloneClass) {
this.cloneName = cloneName;
this.cloneClass = cloneClass;
}
/**
* 默认的 浅拷贝
* @return
* @throws CloneNotSupportedException
*/
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
/**
* @Description 测试代码
*/
public class Client {
public static void main(String[] args) throws Exception {
DeepProtoType protoType = new DeepProtoType();
protoType.setName("宋江");
protoType.setDeepCloneableTarget(new DeepCloneableTarget("大牛", "大年类"));
DeepProtoType clone = (DeepProtoType) protoType.clone();
// DeepProtoType clone = (DeepProtoType) protoType.deepClone();
System.out.println(protoType.getDeepCloneableTarget().hashCode());
System.out.println(clone.getDeepCloneableTarget().hashCode());
}
}
2. 原型模式代码分析
public interface PrototypeInterface extends Cloneable{
PrototypeInterface clone() throws CloneNotSupportedException;
}
public class ProtypeA implements PrototypeInterface {
@Override
public PrototypeInterface clone() throws CloneNotSupportedException {
System.out.println("Cloning new Object: A ");
return (ProtypeA)super.clone();
}
}
public class ProtypeB implements PrototypeInterface {
@Override
public PrototypeInterface clone() throws CloneNotSupportedException {
System.out.println("Cloning new Object: B ");
return (ProtypeB)super.clone();
}
}