您的位置:首页 > 编程语言 > C#

C# 设计模式学习二 Singleton单例模式

2009-12-26 15:16 204 查看
一,模式分类

目的
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
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: