原型模式
这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆,当直接创建对象的代价比较大时,则采用这种方式
例如,一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,
在需要的时候更新数据库,以此来减少数据库调用
原型模式的使用场景
1.资源优化场景
2.类初始化需要消化非常多的资源,包括数据硬件资源等
3.性能和安全要求的场景
4.如果通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式
5.一个对象多个修改者的场景
6.一个对象需要提供给其他对象访问,而且每个调用者都需要修改里面的值时,可以考虑使用原型模式拷贝多个对象供调用者使用
7.在实际项目中原型模式很少单独出现一般是和工厂方法模式一起出现,通过 clone 的方法创建一个对象,然后由工厂方法提供给调用者。
原型模式的优缺点
优点
- Java 自带的原型模式基于内存二进制流的复制,在性能上比直接 new 一个对象更加优良。
- 可以使用深克隆方式保存对象的状态,使用原型模式将对象复制一份,并将其状态保存起来,简化了创建对象的过程,以便在需要的时候使用(例如恢复到历史某一状态),可辅助实现撤销操作。
缺点
- 需要为每一个类都配置一个 clone 方法,比较麻烦
- clone 方法位于类的内部,当对已有类进行改造的时候,需要修改代码,违背了开闭原则
- 当实现深克隆时,需要编写较为复杂的代码,而且当对象之间存在多重嵌套引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来会比较麻烦。因此,深克隆、浅克隆需要运用得当。
原型模式的优结构
- 抽象原型类:规定了具体原型对象必须实现的接口。
- 具体原型类:实现抽象原型类的 clone() 方法,它是可被复制的对象。
- 访问类:使用具体原型类中的 clone() 方法来复制新的对象。
拓展
.二进制流和文本流的区别
在c中引入了流(stream)的概念。它将数据的输入输出看作是数据的流入和留出,这样不管是磁盘文件或者是物理设备(打印机、显示器、键盘等),都可看作一种流的源和目的,视他们为同一种东西,而不管其具体的屋里解构,即对他们的操作,就是数据的流入和流出。这种把数据的输入输出操作对象,抽象化为一种流,而不管它的具体结构的方法很有利于编程,而涉及流的输出操作函数可用于各种对象,与其具体的实体无关,即具有通用性。
在c中流可分为两大类,即文本流和二进制流。
所谓文本流是指在流中流动的数据是以字符形式出现。
二进制流是指流动的是二进制数字序列,若流中有字符,则用一个字节的二进制ASCII码表示,若是数字,则用一个字节的二进制数标识。在流入流出时,对\n符号不进行变换。例如2001这个数,在文本流中用其ASCII码表示为
‘2’ ‘0’ ‘0’ ‘1’
||||
50 48 48 49
共占4字节。而在二进制流中则表示为:00000111 11010001 用十六进制就是07D1。只占两字节。
由此看出,二进制流比文本流节省空间,且不用进行对\n的转换,这样可以大大加快流的速度,提高效率。因而,对于含有大量数字信息的数字流,可以采用二进制流的方式;对于含有大量字符信息的流,则采用文本流的方式。
文本文件与二进制文件的定义
大家都知道计算机的存储在物理上是二进制的,所以文本文件与二进制文件的区别并不是物理上的,而是逻辑上的。这两者只是在编码层次上有差异。
简单来说,文本文件是基于字符编码的文件,常见的编码有ASCII编码,UNICODE编码等等。
二进制文件是基于值编码的文件,你可以根据具体应用,指定某个值是什么意思(这样一个过程,可以看作是自定义编码)
2.深克隆和浅克隆
(1).深克隆
被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍。
(2).浅克隆
被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅复制仅仅复制所拷贝的对象,而不复制它所引用的对象。
详请请看这篇博客:https://www.cnblogs.com/1314xf/p/10139971.html
先做一个小案例简单了解一下
public class Yuanxing implements Cloneable{
Yuanxing(){
System.out.println("具体原型创建成功");
}
//想要返回clone就必须加异常,把克隆的对象返回给object里面
public Object clone() throws CloneNotSupportedException {
System.out.println("具体原型复制成功!");
return (Yuanxing)super.clone();
}
}
//这是一个测试类
class YuanxingCeshi{
public static void main(String[] args) throws CloneNotSupportedException {
Yuanxing y=new Yuanxing();
//在刚刚的类中已经把父类的对象给复制了,通过.clone来获取复制以后的对象
Yuanxing y1= (Yuanxing) y.clone();
System.out.println("y与y1的结果为"+(y==y1));
}
}
运行结果为:
具体原型创建成功
具体原型复制成功!
y与y1的结果为false
总结
原型模式解决的就是对象频繁创建的问题,复制一下,这样效率就比直接new快多了,所以结果为true,那么就这个对象就没有创建成功,也就是没有复制成功,那么自然就违背了原型模式,而如果是false,就说明地址值不一样,就表示对象复制成功
案列二:
public class Bajie implements Cloneable{
Bajie(){
System.out.println("猪八戒可以复制了");
}
public Object clone() throws CloneNotSupportedException {
Bajie b = null;
b = (Bajie) super.clone();
System.out.println("复制成功");
return b;
}
}
class Ceshibajie implements Cloneable{
public static void main(String[] args) throws CloneNotSupportedException {
Bajie b1=new Bajie();
Bajie b2= (Bajie) b1.clone();
if (b1!=b2){
System.out.println("复制成功");
}else{
System.out.println("复制失败");
}
}
}