## 原型设计模式
###
是一种对象创建型模式,使用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象,主要用于创建重复的对象,同时又能保证性能。
####
工作原理是将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝自己来实现创建过程。
###
应该是最简单的设计模式了,实现一个接口,重写一个方法即完成了原型模式。
###
## 应用场景
###
创建新对象成本较大,新的对象可以通过原型模式对已经有的对象进行复制来获得。
如果系统要保存对象的状态,做备份使用。
###
## 原型设计模式涉及到了深拷贝和浅拷贝
###
### 浅拷贝
###
如果原型对象的成员变量是基本数据类型(int、double、byte、boolean、char等),将复制⼀份给克隆对象;
如果原型对象的成员变量是引⽤类型,则将引⽤对象的地址复制⼀份给克隆对象,也就是说原型对象和克隆对象的成员变量指向相同的内存地址;
通过覆盖Object类的clone()⽅法可以实现浅克隆。
###
### 深拷⻉
###
⽆论原型对象的成员变量是基本数据类型还是引⽤类型,都将复制⼀份给克隆对象,如果需要实现深克隆,可以通过序列化(Serializable)等⽅式来实现。
###
**原型模式是内存⼆进制流的拷⻉,⽐new对象性能⾼很多,使⽤的时候记得注意是选择浅拷⻉还是深拷⻉**
###
## 原型设计模式的优点
###
当创建新的对象实例较为复杂时,使⽤原型模式可以简化对象的创建过程,可以提⾼新实例的创建效率
###
可辅助实现撤销操作,使⽤深克隆的⽅式保存对象的状态,使⽤原型模式将对象复制⼀份并将其状态保存起来,以便在需要的时候使⽤恢复到历史状态
###
## 具体实现(云效代码study-java项目当中设计模式当中有代码案例):
###
~~~
package com.goldnecis.设计模式.原型模式;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
public class Persion implements Cloneable, Serializable {
private String name;
private int age;
private List<String> list = new ArrayList<>();
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
public Persion() {
System.out.println("构造函数调用");
}
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 Persion clone() throws CloneNotSupportedException {
return (Persion) super.clone();
}
/**
* 对象深拷贝
* @return
*/
public Object deepClone() {
//首先,创建一个ByteArrayOutputStream对象baos,它是一个字节数组输出流,用于将对象序列化为字节数组。
//然后,创建一个ObjectOutputStream对象oos,它是一个对象输出流,用于将对象写入baos中进行序列化操作。
//通过调用oos.writeObject(this),将当前对象this写入baos,实现对象的序列化。
//接下来,创建一个ByteArrayInputStream对象bais,它是一个字节数组输入流,用于从字节数组中读取对象数据。
//然后,创建一个ObjectInputStream对象ois,它是一个对象输入流,用于从bais中读取对象并进行反序列化操作。
//通过调用ois.readObject(),从bais中读取反序列化的对象数据,并将其转换为Persion类型的对象copyObj。
//最后,返回copyObj作为方法的结果,表示深拷贝后得到的新对象。
//如果在序列化或反序列化过程中出现异常,将打印异常堆栈信息,并返回null。
try {
//输出 序列化
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(this);
//输入 反序列化
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
Persion copyObj = (Persion) ois.readObject();
return copyObj;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
~~~
再来看如何调用进行深浅拷贝
###
~~~
package com.goldnecis.设计模式.原型模式;
//原型模式的实现
//其实就是类的深拷贝和浅拷贝
public class Main {
public static void main(String[] args) throws CloneNotSupportedException {
Persion person1 = new Persion();
person1.setAge(10);
person1.setName("小滴课堂-老王");
//首先被拷贝对象的list当中已经有了aaa 如果是浅拷贝 person1当中aaa如果persion2设置了ccc那么person1当中的list也会有ccc结果就是aaa,ccc persion2当中也是aaa,ccc
//如果是深拷贝,person1当中的list就是aaa 因为是深拷贝 所以persion2当中再去设置ccc和persion1就没有任何的关系 所以persion2当中的list就是aaa,ccc persion1当中就是aaa
person1.getList().add("aaa");
//浅拷贝
//如果是浅拷贝并且如果原型对象的成员变量是基本数据类型(int double byte boolean char 等)将复制一份给克隆对象
//如果原型对象的成员变量是引用数据类型,则将引用对象的内存地址复制一份给克隆对象,也就是说原型对象和克隆对象的成员变量指向相同的内存地址
//通过覆盖Object类的clone()方法可以实现浅拷贝
Persion persion2 = person1.clone();
//深拷贝
//无论原型对象的成员变量是基本数据类型还是引用数据类型,都将复制一份给克隆对象,如果需要实现深克隆,可以通过序列化Serializable等方式来实现
//原型模式是内存二进制流的拷贝,比new对象性能高很多,使用的时候记得注意是选择浅拷贝还是深拷贝
//Persion persion2 = (Persion) person1.deepClone();
persion2.setName("Anna小姐姐");
persion2.getList().add("ccc");
System.out.println("person1="+person1.getName()+", age="+person1.getAge());
System.out.println("person2="+persion2.getName()+", age="+persion2.getAge());
//首先被拷贝对象的list当中已经有了aaa 如果是浅拷贝 person1当中aaa如果persion2设置了ccc那么person1当中的list也会有ccc结果就是aaa,ccc persion2当中也是aaa,ccc
//如果是深拷贝,person1当中的list就是aaa 因为是深拷贝 所以persion2当中再去设置ccc和persion1就没有任何的关系 所以persion2当中的list就是aaa,ccc persion1当中就是aaa
System.out.println(person1.getList().toString());
System.out.println(persion2.getList().toString());
}
}
~~~
###
![](https://img.kancloud.cn/cf/ea/cfea675a7b73dd83eac03572143a1e72_1876x953.png)
###
![](https://img.kancloud.cn/f9/eb/f9ebbeef18e12b80c8f06cc5badd244e_1609x870.png)
- 设计模式六大原则
- 常见的三大设计模式分类
- 创建型模式之单例模式
- 单例模式之懒汉
- 单例模式之饿汉
- 单例模式之如何选择懒汉饿汉
- 什么情况下使用单例模式
- 创建型模式之工厂模式
- 简单工厂模式
- 工厂方法模式
- 抽象工厂模式
- 创建型模式之原型模式
- 创建型模式之建造者模式
- 结构型模式之适配器模式
- 接口的适配器模式
- 类的适配器模式
- 结构型模式之桥接模式
- 结构型模式之桥接模式和适配器模式的区别
- 结构型模式之装饰器模式
- 结构型模式之代理模式
- 结构模式之外观模式
- 结构模式之享元模式
- 行为模式之策略模式
- 行为模式之模板模式
- 行为模式之观察者模式
- 行为模式之责任链模式
- 行为模式之命令模式
- 行为模式之迭代器模式
- 行为模式之备忘录模式
- 行为模式之状态模式