C# 设计模式之Singleton单例模式
本文导语: 一,模式分类 目的 1,创建型 Creational模式 负责对象创建 2,结构型 Structural模式 处理类与对象间的组合 3,行为型 Behavior 模式 类与对象交互中的职责分配 范围 1,类模式处理类与子类的静态关系 2,对象模式处理对...
一,模式分类
目的
2,结构型 Structural模式 处理类与对象间的组合
3,行为型 Behavior 模式 类与对象交互中的职责分配
范围
2,对象模式处理对象间的动态关系
二,Singleton模式
1,动机Motivation
在软件系统中 有一些特殊类,必须保证他们在系统中只有一个存在(只有一个实例)才能保证他们的逻辑正确性,以及良好的效率。
这种动机是类的设计者的责任(由设计类的人保证),而不是使用者的责任。
如何绕过常规的构造器,提供一种机制来保证一个类只有一个实例。
2,意图
保证一类只有一个实例,并提供一全局访问点
三,Singleton模式的要点
1,Singleton模式中的实例构造器可以设置为protected以允许子类派生
2,Singleton模式不需要支持Icloneable接口(该接口用于克隆),会导致多个对象实例
3,一般不要支持序列化,同上(序列化的方式也可以创建对象)
4,只考虑了对象创建管理,没有考虑对象销毁的管理。因为开销较小(仅有一个),所以没有必要对其销毁进行特殊的管理。
5,不能应用多线程环境,在多线程环境中,使用Singleton模式任然有可能得到多个实例对象。
四,Singleton模式的扩展
1,将一个实例扩展到n个实例,例如对象池的实现
n并不是任意,而是可控制的范围,
如,建立一个服务队列,在初始化的过程中用new构造出n个对象,再轮询调用
2,将new构造器的调用转移到其他类中,例如多个类协同工作环境中,某个局部环境只需要拥有一个类的一个实例
3,理解和扩展Singleton模式的核心是:“如何控制用户使用new对一个类的实例构造器的任意调用”
即使很好的控制new,new太自由
五,实例
1,单线程Singleton模式
public class Singleton
{
private static Singleton instance;
//私有构造器(屏蔽默认构造器),不会被构造,只能在类的内部使用这个私有构造器
private Singleton() { }
//静态属性
public static Singleton Instance
{
get
{
if (instance == null)
{
//只能在类的内部使用这个私有构造器
instance = new Singleton();
}
return instance;
}
}
}
//参数化的Singleton模式
public class Singleton1
{
private static Singleton1 instance;
int x, y;
private Singleton1(int x, int y)
{
this.x = x;
this.y = y;
}
public static Singleton1 Instance(int x, int y)
{
if (instance == null)
{
instance = new Singleton1(x, y);
}
else
{
instance.x = x;
instance.y = y;
}
return instance;
}
}
2,多线程Singleton模式
class Singleton2
{
//volatile修饰,保证编译器不会调整我们定义的代码(编译器有可能在编译过程中微调代码)
private static volatile Singleton2 instance = null;
//辅助器,只要是object子类就可以,不是模式中的元素
private static object lockHelper = new object();
private Singleton2() { }
//静态属性
public static Singleton2 Instance
{
get
{
//先判断是否存在,再加锁,否则影响性能
if (instance == null)
{
//锁住括号中的执行内容,直到执行结束
//这里注意lock的内容是所有实例都是用的元素,比如本类中的静态变量lockHelper
lock (lockHelper)
{
//双检查,避免多线程访问错误(同时进入if语句),new出多个实例
if (instance == null)
{
instance = new Singleton2();
}
}
}
return instance;
}
}
}
3,更好的Singleton模式的实现(多线程对应)
//更好的Singleton模式的实现(多线程对应)
//密封类不可以继承
sealed class Singleton3
{
/*
* ① 实现了内联初始化,实际上编译后静态字段会被加入静态构造器中执行(实现初始化)
* 而我们在使用静态变量之前,类的静态构造器会被首先执行
* 所以我们只要方法该字段就能保证它们初始化
* ② 支持多线程,
* .net机制本身就保证只有一个线程能执行静态构造器,可以免费为静态构造器加锁
* ③ 弊端
* 该方式不能支持带参数的构造器
* 根本原因在于静态构造器是私有的,不带参数的,
* 在一定程度上,可以定义一些属性来解决这一问题(如果仅仅是简单的设置值的话),或者
* 定义个单独的初始化方法来实现初始化,如,加入public void Init() { ...}方法实现初始化
* ④ 而且由于类一加载就实例化对象,所以要提前占用系统资源(前面都是用时才实例化)
*/
public static readonly Singleton3 Instance = new Singleton3();
private Singleton3() { }
}
//上类等同于此类
class Singleton4
{
public static readonly Singleton4 Instance;
//静态的构造器,执行时间
static Singleton4()
{
Instance = new Singleton4();
}
private Singleton4() { }
}
4,其他实例
//一,.net环境中GetType方法返回的对象,就是用了该模式
int[] array1 = new int[] { 1, 2, 3 };
int[] array2 = new int[] { 4, 5, 6 };
Type t1 = array1.GetType();
Type t2 = array2.GetType();
//ReferenceEquals判断t1,t2是否指向同一地址
Console.WriteLine(ReferenceEquals(t1, t2));
//结果为true
//二,在配置类中访问的HttpContext都是全局唯一的对象
//HttpContext.Current
}