单例模式解决的问题:当我们只需要一个实例对象的时候,不希望有很多实例对象,此时用单例模式。
那么问题来了,当我们需要很多很多实例对象的时候,怎么办???
1 单线程中, 每次都new一个对象,new 很多很多次-----> 缺点:每次都需要调用构造函数,很耗时
2 由 1 ,想到用多线程解决,本质上还是new出很多对象,并未解决每次调用构造函数耗时的问题。
3 主角来了:这种情况下,采用原型模式,即可解决。
原理:通过java中clone的方式进行对象的克隆(复制)(这里还涉及到浅复制和深复制),而不用经过构造函数创建对象,实际上只需要经过一次构造函数生成对象,剩下的都是通过这个对象进行复制生成。
形象举例:西游记都知道,孙悟空拔猴毛变出许多小猴子,这就是个原型模式。孙悟空本尊就是通过构造函数生成的,就是正常渠道生成的,即石头缝里蹦出来的,那么当我们想要得到许多孙悟空时是不是每次都要重新从石头缝里蹦出猴子呢,显然不是,如果需要10万个猴子,要是全从石头缝里蹦出来,那得需要蹦到什么时候。于是,从石头缝里蹦出来的有且仅有一个猴子(构造函数只使用一次),剩下的由这个猴子再拔猴毛生成(调用java的clone函数,复制生成的对象,而不是每次都new个对象)。
原型模式的特点:
1 由原型对象自身创建目标对象
2 目标对象是原型对象的克隆
3 对象克隆分为:浅度克隆和深度克隆
代码:
SunWuKong 类实现了Cloneable接口
public class SunWuKong implements Cloneable {
public SunWuKong()
{
System.out.println("once");
}
public SunWuKong getNewSunWuKong()
{
SunWuKong s = null;
try
{
s = (SunWuKong) super.clone();
} catch (Exception e)
{
}
return s;
}
}
测试代码:
public static void main(String[] args) {
SunWuKong s1=new SunWuKong();
SunWuKong s2=s1.getNewSunWuKong();
SunWuKong s3= s1.getNewSunWuKong();
System.out.println(s2==s1);
System.out.println(2);
}
注:参考博文:https://www.cnblogs.com/xiaobai1226/p/8488332.html
1 克隆并不等同于SunWuKong s2 = s1;像SunWuKong s2 = s1;指的是在栈中创建一个变量p2,将p1的内存地址赋给p2,其实指的是同一个对象。而克隆是复制出一份一模一样的对象,两个对象内存地址不同,但对象中的结构与属性值一模一样(这里,Java和python的特性,变量是对对象的引用,变量指向对象)。
2 这种不通过 new 关键字来产生一个对象,而是通过对象拷贝来实现的模式就叫做原型模式,这个模式的核心是一个clone( )方法,通过这个方法进行对象的拷贝,Java 提供了一个 Cloneable 接口来标示这个对象是可拷贝的,为什么说是“标示”呢?翻开 JDK 的帮助看看 Cloneable 是一个方法都没有的,
这个接口只是一个标记作用,在 JVM 中具有这个标记的对象才有可能被拷贝,所以覆盖了覆盖clone()方法就可以了。
在 clone()方法上增加了一个注解@Override, 没有继承一个类为什么可以重写呢?在 Java 中所有类的父类是Object 类,每个类默认都是继承了这个类,所以这个用上@Override是非常正确的。原型模式虽然很简单,但是在 Java 中使用原型模式也就是 clone 方法还是有一些注意事项的:
对象拷贝时,类的构造函数是不会被执行的。 一个实现了 Cloneable 并重写了 clone 方法的类 A,有一个无参构造或有参构造 B,通过 new 关键字产生了一个对象 S,再然后通过 S.clone()方式产生了一个新的对象 T,那么在对象拷贝时构造函数 B 是不会被执行的, 对象拷贝时确实构造函数没有被执行,这个从原理来讲也是可以讲得通的,Object 类的 clone 方法的 原理是从内存中(具体的说就是堆内存)以二进制流的方式进行拷贝,重新分配一个内存块,那构造函数 没有被执行也是非常正常的了。从另一个方面来说,构造函数没有必要执行,原因是,构造函数的作用是在创建对象的时候对类对象中的属性进行初始化,这里原型已经有了,也就是说其实对象的成员属性已经初始化好了,那么再复制的时候直接用就是,没有必要再 进行初始化,因此也就没有必要进行调用构造函数。
深浅拷贝
原型模式中,涉及到clone方法,即复制对象,在java中对对象进行复制时,涉及到深浅拷贝的问题,简而言之,
对于基本数据类型的变量(int, boolean, char , byte, short , float ,double 以及long)会重新复制一份,对基础的数据类型不涉及到深浅拷贝概念,而对于引用类型的变量(数组,类对象等),浅拷贝是只复制引用变量,不复制原引用所指向的对象,而深拷贝指的是不仅复制了新的引用变量,同时,引用变量的对象还复制了一份,(区别就是引用所指向的对象有没有复制一份)。
参考博文:https://www.cnblogs.com/dolphin0520/p/3700693.html(浅谈深拷贝和浅拷贝)
怎么实现???
搜索博客:Java设计模式:23种设计模式全面解析(超级详细)
链接:https://www.baidu.com/link?url=e1QQ5H1_aO62Kc8XO1Y6NB5YatdhOdPhbYprcN71Hs8NaedUDMtNmiOCX3OSFrYu&wd=&eqid=9693bbca000b1c59000000035d07a3ca
---------------------
百度+敲代码。