单例模式(Singleton Pattern)
意图
保证一个类仅有一个实例,并提供一个该实例的全局访问点
可将一个实例扩展到n个实例。限定某类最多只能创建n个实例。
双重锁定实现单例模式
C#
public sealed class Singleton { private static volatile Singleton instance = null; private static readonly object lockHelper = new object(); private Singleton() { } public static Singleton Instance { get { if (instance == null) { lock (lockHelper) { if (instance == null) { instance = new Singleton(); } } } return instance; } } }
解决了线程并发问题,同时避免在每个 Instance 属性方法的调用中都出现独占锁定。还实现了惰性实例化。
volatile修饰:编译器在编译代码的时候会对代码的顺序进行微调,用volatile修饰保证了严格意义的顺序。一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。
JAVA的双重校验单例模式
public final class Singleton { private volatile static Singleton singleton; private Singleton() { } public static Singleton getSingleton() { if (singleton == null) { synchronized (Singleton.class) { if (singleton == null) { singleton = new Singleton(); } } } return singleton; } }
利用类加载器
没有懒加载,利用类装载时实例化,避开了多线程的问题
C#
public sealed class Singleton { private static Singleton instance = new Singleton(); static private Singleton() { } public static Singleton getInstance() { return instance; } }
java
public final class Singleton { private static Singleton instance = new Singleton(); private Singleton() { } public static Singleton getInstance() { return instance; } }
类加载器+内部类/嵌套类
同样采用类加载器避开多线程同步问题,这里却可以只在内部类/嵌套类被调用时加载。优于上一方法。
C#的嵌套类
public sealed class Singleton { private Singleton() { } public static Singleton getInstance() { return Nested.instance; } private class Nested { internal static readonly Singleton instance = new Singleton(); } }
JAVA的静态内部类
public final class Singleton { private Singleton() { } public static final Singleton getInstance() { return SingletonHolder.INSTANCE; } private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } }
java利用枚举
java的枚举常量本身就是实例,而且枚举不能在运行时实例化。
public enum Singleton { INSTANCE; public void whateverMethod() { } class whateverClass{ } }
swift 中单例模式
swift从1.2开始,类中可以使用static修饰词,自带懒加载特性
class Singleton{ static let instance = Singleton() }