1.目的
控制实例的个数,类设计者应该保证只有一个实例,不能将此责任【只有一个实例】强制交给类使用者。
2.整体实现
1.单线程单例模式的实现。
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace LearnDesignPattern { public class Singleton { private Singleton() { }//构造函数私有化,使得用户无法通过new关键字创建对象 private static Singleton instance; public static Singleton Instance { get {//懒加载模式,用户也可以每次获取的时候,都new,但是这样不推荐 //首先判断,如果为第一次使用,则进行new if (instance == null) { instance = new Singleton(); } return instance; } } //注意【1】,C#的单例模式一般使用属性来获取Instance //而在Java,中一般使用public static Singleton getInstance()的方法,这点不同 //注意【2】,为什么要使用Static关键字呢,我们知道Static的关键字的作用是 //可以直接通过类名来进行调用,这样就保证了,需要先有类的实例才能获取 //非static属性的情况 } }
2.多线程单例模式实现:
//如果两个线程同时判断instance是不是为空,当instance==null的时候 //两个线程就同时创建出来实例,这样就存在了两个实例了 public class Singleton { private Singleton() { } //volatile:被volatile修饰的变量的值,将不会被本地线程换缓存 //所有对该变量的读写都是直接操作共享内存,从而确保多个线程能 //正确的处理该变量 private static volatile Singleton instance; //添加线程锁,确保只有一个线程可以访问该范围的代码,其他线程等待 private static object objectLock = new object(); public static Singleton Instance { //double check双重检查机制 get { if (instance == null) { lock (objectLock) { if (instance == null) { instance = new Singleton(); } } } return instance; } } }
3.经典的多线程单例模式写法。
//【使用静态构造器】 //1.静态构造函数既没有访问修饰符,也没有参数 //2.在创建第一个实例或引用任何静态成员之前,将自动调用静态构造函数来初始化类 //3.无法直接调用静态构造函数 //4.在程序中,用户无法控制何时执行静态构造函数 //【保证1】保证使用类实例或者静态成员之前初始化 //【保证2】懒加载,只有在第一次使用,才调用静态构造器 //【保证3】.net框架会自动为多线程加锁 public static readonly Singleton Instance = new Singleton(); private Singleton() { } //【弊端】不支持参数化Singleton,因为传参必须使用方法来进行!!!GetInstance(object a,object b){}
4.参数化Singleton
//参数化Singleton private Singleton(int a,int b) { this.A = a;//A、B均为静态属性 this.B = b;//A、B均为静态属性 } public static Singleton GetInstance(int x, int y) { if (instance == null) { instance= new Singleton(x, y); } //可修改单例模式!就相当于修改当前单例的属性,并不会重新创建新的实例 else { instance.A = x;//A、B均为静态属性 instance.B = y;//A、B均为静态属性 } return instance; }
3.思考
1.实例的个数可以两个么?三个......多个。使用时,一次创建多个,放在池子中,使用的时候去取。
2.如何将new构造器放到其他类中,实现局部使用一个对象的实例。
3.将new进行屏蔽,然后通过其他方法来实现new的效果【不仅仅是单例】。