设计模式之单例模式 - morris131/morris-book GitHub Wiki
一个类有且仅有一个实例,并且自行实例化向整个系统提供。
HungerSingleton.java
package com.morris.pattern.singleton;
/**
* 饿汉式单例,类加载时初始化单例对象
*/
public class HungerSingleton {
private static HungerSingleton singleton = new HungerSingleton();
private HungerSingleton() {
}
public static HungerSingleton getInstance() {
return singleton;
}
}
LazySingleton.java
package com.morris.pattern.singleton;
/**
* 懒汉式单例类,线程不安全
*/
public class LazySingleton {
private static LazySingleton singleton;
private LazySingleton() {
}
public static LazySingleton getInstance() {
if (null == singleton) {
singleton = new LazySingleton();
}
return singleton;
}
}
SyncMethodLazySingleton.java
package com.morris.pattern.singleton;
/**
* 懒汉式单例类,同步方法,线程安全,效率很低,99%情况下不需要同步。
*/
public class SyncMethodLazySingleton {
private static SyncMethodLazySingleton singleton;
private SyncMethodLazySingleton() {
}
public static synchronized SyncMethodLazySingleton getInstance() {
if (null == singleton) {
singleton = new SyncMethodLazySingleton();
}
return singleton;
}
}
StaticInnerClassSingleton.java
package com.morris.pattern.singleton;
/**
* 静态内部类,单例,Singleton类被装载了,instance不一定被初始化,达到懒加载。
*/
public class StaticInnerClassSingleton {
private static class SingletonHolder {
private static final StaticInnerClassSingleton INSTANCE = new StaticInnerClassSingleton();
}
private StaticInnerClassSingleton() {
}
public static final StaticInnerClassSingleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
EnumSingleton.java
package com.morris.pattern.singleton;
/**
* 枚举单例,不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象
*/
public enum EnumSingleton {
INSTANCE;
public void whateverMethod() {
}
}
DoubleSyncLockSingleton.java
package com.morris.pattern.singleton;
/**
* 双重同步锁
*/
public class DoubleSyncLockSingleton {
private volatile static DoubleSyncLockSingleton singleton;
private DoubleSyncLockSingleton() {
}
public static DoubleSyncLockSingleton getSingleton() {
if (singleton == null) {
synchronized (DoubleSyncLockSingleton.class) {
if (singleton == null) {
singleton = new DoubleSyncLockSingleton();
}
}
}
return singleton;
}
}
- 在内存中只有一个对象,节省内存空间
- 避免频繁的创建销毁对象,可以提高性能
- 避免对共享资源的多重占用
- 可以全局访问
- 没有接口,不能继承,无法扩展。
- 与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。
- 要求生成唯一序列号的环境;
- 在整个项目中需要一个共享访问点或共享数据,例如一个Web页面上的计数器,可以不用把每次刷新都记录到数据库中,使用单例模式保持计数器的值,并确保是线程安全的;
- 创建一个对象需要消耗的资源过多,如要访问IO和数据库等资源;
- 需要定义大量的静态常量和静态方法(如工具类)的环境