设计模式之单例模式 - morris131/morris-book GitHub Wiki


title: 设计模式之单例模式 date: 2018-09-19 10:05:22 categories: 设计模式 tags: [设计模式,单例模式]

设计模式之单例模式

定义

一个类有且仅有一个实例,并且自行实例化向整个系统提供。

类图

单例模式类图

实现

饿汉式单例

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和数据库等资源;
  • 需要定义大量的静态常量和静态方法(如工具类)的环境
⚠️ **GitHub.com Fallback** ⚠️