C# 设计模式之Singleton单例模式

发布时间:2020-06-21编辑:脚本学堂
本文介绍下,C#编程中的设计模式之单例模式,英文叫作Singleton,先讲理论,后举实例,方便大家学习参考。

一,模式分类
目的
 

1,创建型 Creational模式 负责对象创建
2,结构型 Structural模式 处理类与对象间的组合
3,行为型 Behavior 模式  类与对象交互中的职责分配

范围
 

1,类模式处理类与子类的静态关系
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模式
 

复制代码 代码示例:
  //单线程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模式
 

复制代码 代码示例:
//多线程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 
}