【设计模式】单例模式
个人理解,单例模式就是创建一个独一无二的对象,在我们需要时才创建,如果用全局静态变量代替的话,就必须在程序一开始就创建,可能造成资源浪费。
单例模式确保一个类只有一个实例,并提供一个全局的访问点。
先来看看一个经典的单例模式代码:
1 package cn.sp.singleton;
2 /**
3 * 单例模式 -- 使用懒加载 -- 只适合单线程
4 * @author 2YSP
5 *
6 */
7 public class Singleton {
8
9 private static Singleton singleton;
10
11 private Singleton(){
12
13 }
14
15 public static Singleton getInstance(){//但是如果是多线程的话,会产生不同的实例,而不是一个独一无二的对象
16 if(singleton == null){
17 singleton = new Singleton();
18 }
19
20 return singleton;
21 }
22 }
但是如果是多线程的话,会出问题。以下是改进后的代码。
1 package cn.sp.singleton;
2 /**
3 * 单例模式 -- 使用懒加载 -- 多线程版
4 * @author 2YSP
5 *
6 */
7 public class Singleton2 {
8
9 private static Singleton2 singleton;
10
11 private Singleton2(){
12
13 }
14
15 public synchronized static Singleton2 getInstance(){//使用同步,但是执行效率降低
16 if(singleton == null){
17 singleton = new Singleton2();
18 }
19
20 return singleton;
21 }
22 }
package cn.sp.singleton;
/**
* 单例模式 -- 立即创建 -- 多线程版
* @author 2YSP
*
*/
public class Singleton3 {
private static Singleton3 singleton = new Singleton3();
private Singleton3(){
}
//如果应用程序总是创建并使用单件实例,或者在创建和运行方面的负担不太繁重,可使用此方法
public static Singleton3 getInstance(){
return singleton;
}
}
1 package cn.sp.singleton;
2 /**
3 * 单例模式 -- 加锁 -- 多线程版
4 * @author 2YSP
5 *
6 */
7 public class Singleton4 {
8
9 private volatile static Singleton4 singleton ;//volatile 关键字保证变量的可见性
10
11 private Singleton4(){
12
13 }
14 //使用“双重检查加锁”,在getInstance()中减少使用同步,提示效率
15 public static Singleton4 getInstance(){
16 if(singleton == null){
17 synchronized (Singleton4.class) {
18 if(singleton == null){
19 singleton = new Singleton4();
20 }
21 }
22 }
23 return singleton;
24 }
25 }
推荐使用枚举实现单例模式,因为不光线程安全还不会因为序列化而产生新实例,防止反射攻击,具体可以查看这篇文章https://www.cnblogs.com/happy4java/p/11206105.html。