1.Java 面试之单子模式
单子模式要满足以下几点
1, 构造函数私有化,使得不能通过new来实例化对象
2,通过new在类的内部创建唯一的实例化对象
3,定义一个公有的静态的方法来返回上一部的对象
单子模式分为懒汉模式和饿汉模式
饿汉模式*
以下通过代码来讲解什么饿汉模式
public class Single {
//1 私有构造器。外部不能访问
private Single(){
}
//2 声明一个静态的自己的类
private static Single single = new Single();
//3 返回一个返回自己类的方法
public static Single getInstance(){
return single;
}
}
测试类:打出实例化之后的对象地址
public class Test {
public static void main(String[] args) {
Single single1 = Single.getInstance();
Single single2 = Single.getInstance();
System.out.println(single1);
System.out.println(single2);
}
}
运行结果
:Test.main()
csdn.Single@15db9742
csdn.Single@15db9742
发现地址都一样,说明实例化的是一个对象
特点是不管对象有没有为空,直接实例化
懒汉模式
public class Single2 {
private Single2(){}
private static Single2 single2;
public static Single2 getInstance(){
if(single2==null){
single2 = new Single2();
}
return single2;
}
}
public class Test {
public static void main(String[] args) {
Single2 single1 = Single2.getInstance();
Single2 single2 = Single2.getInstance();
System.out.println(single1);
System.out.println(single2);
}
}
运行结果:
:Test.main()
csdn.Single2@15db9742
csdn.Single2@15db9742
可以看出地址是一样的,懒汉模式一旦第一次实例化成功后,这个对象就不动了,因为是static
还有就是因为要判断一次对象是否为空,这也是他和饿汉的区别,他相比较,实例化比较温柔
但是由于在多线程操作下,对象判空这一项会受到多线程的影响,可能线程a进行了实例化但是线程b同时进行判空就会发生错误,所以就要对实例化判断进行同步锁的注入
代码:
public class Single3 {
private static Single3 single3;
private Single3(){}
public static Single3 getInstance(){
synchronized (Single3.class){
if(single3==null){
single3 = new Single3();
}
}
return single3;
}
}
这样就解决了多线程并发的错误
但还是缺点:每次调用方法时都要加锁,而加锁很耗时,所以在保证对象为null时只new出一个实例时加锁就够了
改进如下:
public class Single4 { private static Single4 single4;
private Single4(){}
public static Single4 getInstance(){
if(single4==null){
synchronized (Single4.class){
if(single4==null){
single4 = new Single4();
}
}
}
return single4;
}
}
静态代码块
在静态代码块中加入对该自身对象的实例化,因为JDK会在静态代码区中对其代码仅执行一次
public class Single5 {
private Single5(){}
private static Single5 single5;
static{//本身就是线程同步且仅执行一次
single5 = new Single5();
}
//这里不需要加锁,因为他会在jdk区进行单线程的实例化
public static Single5 getInstance(){
return single5;
}
}
结果:
:Test.main()
csdn.Single5@15db9742
csdn.Single5@15db9742
静态代码按需创建(静态内部类)
如果按上面的方法,在执行静态方法后会对程序产生影响,为了避免这个问题,改进一个内部类的手段进行优化:
public class Single6 {
private Single6(){}
//建立内部类
private static class Nested{
private static Single6 single6;
static{
single6 = new Single6();
}
}
public static Single6 getInstance(){
return Nested.single6;
}
}
以上就是所有的单子模式,欢迎补充