单例模式-----创建型模式设计
定义是单例对象的类只能允许一个实例存在
单例的实现主要是通过以下两个步骤:
- 将该类的构造方法定义为私有方法,这样其他处的代码就无法通过调用该类的构造方法来实例化该类的对象,只有通过该类提供的静态方法来得到该类的唯一实例;
- 在该类内提供一个静态方法,当我们调用这个方法时,如果类持有的引用不为空就返回这个引用,如果类保持的引用为空就创建该类的实例并将实例的引用赋予该类保持的引用
应用场景: window 系统的 回收站实例。网站的计数器 等 web 的 HttpApplication对象
优点:
-
在内存中只有一个对象,节省内存空间;
-
避免频繁的创建销毁对象,可以提高性能;
-
避免对共享资源的多重占用,简化访问;
-
为整个系统提供一个全局访问点。
扫描二维码关注公众号,回复: 9412641 查看本文章
缺点:
-
不适用于变化频繁的对象;
-
滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为的单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;
-
如果实例化的对象长时间不被利用,系统会认为该对象是垃圾而被回收,这可能会导致对象状态的丢失;
懒汉式
/** * 懒汉式单例模式
* 只有在真正使用的时候才会实例化一个对象并交给自己的引用 * **/ public class Singleton { // 静态实例 private static Singleton singleton; //私有化构造函数 private Singleton(){ } /** * * 静态办法。返回一个实例 * 在并发情况下,这样子是不安全的。 * 因为 if 判断哪里。 会出现 A刚好进去,还没创建实例, * B这时候刚好 也在if 判断,此时的实例是为空的,符合判断,所以也进去了。 * 会出现多个实例的问题。 * * */ public static Singleton getInstance(){ if(singleton==null){ singleton = new Singleton(); } return singleton; } }
饿汉式
/** * 饿汉式单例 * * 优点:这种写法比较简单,就是在类装载的时候就完成实例化。避免了线程同步问题。 * * 缺点:在类装载的时候就完成实例化,没有达到Lazy Loading的效果。如果从始至终从未使用过这个实例,则会造成内存的浪费 * */ public class Singleton1 { // 指向自己实例的私有静态引用,主动创建 private static Singleton1 singleton1 = new Singleton1(); // 私有的构造方法 private Singleton1(){} // 以自己实例为返回值的静态的公有方法,静态工厂方法 public static Singleton1 getSingleton1(){ return singleton1; } }
双重加锁机制
public class Singleton { private static Singleton instance; //程序运行时创建一个静态只读的进程辅助对象 private static readonly object syncRoot = new object(); private Singleton() { }
//双重检测同步延迟加载去创建单例的做法是一个非常优秀的做法,其不但保证了单例,而且切实提高了程序运行效率 优点:线程安全;延迟加载;效率较高。
public static Singleton GetInstance()
{ //先判断是否存在,不存在再加锁处理 if (instance == null) { //在同一个时刻加了锁的那部分程序只有一个线程可以进入 lock (syncRoot) { if (instance == null) { instance = new Singleton(); } } } return instance; } }
静态初始化
//阻止发生派生,而派生可能会增加实例 public sealed class Singleton { //在第一次引用类的任何成员时创建实例,公共语言运行库负责处理变量初始化 private static readonly Singleton instance=new Singleton(); private Singleton() { } public static Singleton GetInstance() { return instance; } }