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的效果【不仅仅是单例】。