NET中的设计模式---单件模式
2015-06-23 09:47
302 查看
如众所知,单件模式做为<Gof 23中设计模式>之一,其意图仅允许单件类的一个实例存在(扩展单件模式不在此文范围内),并提供全局的访问方法.UML类图如下.
http://csharpindepth.com/Articles/General/Singleton.aspx一文中列举了单件模式实现的5种方法,但诸多文章中都或多或少的遗漏一些问题:如何保证线程安全,如何保证仅有一个实例存在,如何根据业务变化扩展.
下面以C#实现单件为例,对这些问题一一说明.
1. 如何保证线程安全
在C#中可以使用static,readonly两个关键字保证单件的线程安全.static关键字修饰的静态成员在程序运行时由 .NET Framework 公共语言运行库 (CLR) 自动加载管理,这些成员是密封的,全局的,且不能被实例化。诸如此类的特点,让C#中的单件实现更加方便简洁.readonly关键字可用于保证对单件实例的引用在任何情况下不被修改.也因此与static一起保证单件的线程安全.
2. 如何保证仅有一个实例存在
在C#中,static关键字保证了对单件实例的唯一引用,隐藏构造函数保证无法通过new构造对象.但这并不能保证单件实例的唯一性.如我们可以反序列化出一个单件类型的实例,也可以通过实现克隆接口克隆一个单件的实例.
因此我们要保证单件类型不能被序列化,不能被克隆,即不能为单件类型及扩展类型添加Serializable标签和实现克隆接口或方法.
3. 如何扩展
除了在<Gof 23种设计模式>一书中提及对单件类型的扩展之外,很少有文章提到对单件类的继承扩展,甚至有的C#实现方式中直接将单件类前加上了sealed关键字来密封单件类.但是在实际项目中,业务需求的多变必然要求单件类能够被继承.Gof一书中提到了使用注册单件的方法实现单件类的继承.在C#中,我们可以使用继承类扩展单件类,使用反射来根据需求装载不同的单件子类型.
下面是具体的代码示例,示例中演示了C#中单件的一种实现方式和对单件类的继承.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
namespace SingletonDemo
{
class Program{
static void Main(string[] args){
try{
Singleton s1 = Singleton.Instance;
Console.WriteLine("This is {0}.", s1.Name);
Singleton sc = s1.Clone();
Console.WriteLine("This is {0}.", sc.Name);
s1.Name = "小小";
Console.WriteLine("This is {0}.", s1.Name);
Console.WriteLine("This is {0}.", sc.Name);
MySingleton s2 = MySingleton.Instance as MySingleton;
Console.WriteLine("{0} is {1} year old.", s2.Name, s2.Age);
}
catch (Exception ex){
Console.WriteLine("Error:{0}",ex.Message);
}
}
}
public class Singleton{
public string Name = "倪大虾";
//readonly可以保证线程安全
static readonly Singleton instance = Create();
static Singleton(){
}
protected Singleton(){
}
public static Singleton Instance{
get{
return instance;
}
}
private static Singleton Create(){
try{
//从外部(注册表,配置文件...)导入
string typeName = "SingletonDemo.MySingleton";
Type t = Type.GetType(typeName);
ConstructorInfo ci = t.GetConstructor(new Type[]{});
return (Singleton)ci.Invoke(null);
}
catch (Exception ex){
throw ex;
}
}
/*//不能实现克隆方法
public Singleton Clone(){
return new Singleton();
}*/
}
[Serializable]
public class MySingleton:Singleton{
public int Age = 28;
}
}
http://csharpindepth.com/Articles/General/Singleton.aspx一文中列举了单件模式实现的5种方法,但诸多文章中都或多或少的遗漏一些问题:如何保证线程安全,如何保证仅有一个实例存在,如何根据业务变化扩展.
下面以C#实现单件为例,对这些问题一一说明.
1. 如何保证线程安全
在C#中可以使用static,readonly两个关键字保证单件的线程安全.static关键字修饰的静态成员在程序运行时由 .NET Framework 公共语言运行库 (CLR) 自动加载管理,这些成员是密封的,全局的,且不能被实例化。诸如此类的特点,让C#中的单件实现更加方便简洁.readonly关键字可用于保证对单件实例的引用在任何情况下不被修改.也因此与static一起保证单件的线程安全.
2. 如何保证仅有一个实例存在
在C#中,static关键字保证了对单件实例的唯一引用,隐藏构造函数保证无法通过new构造对象.但这并不能保证单件实例的唯一性.如我们可以反序列化出一个单件类型的实例,也可以通过实现克隆接口克隆一个单件的实例.
因此我们要保证单件类型不能被序列化,不能被克隆,即不能为单件类型及扩展类型添加Serializable标签和实现克隆接口或方法.
3. 如何扩展
除了在<Gof 23种设计模式>一书中提及对单件类型的扩展之外,很少有文章提到对单件类的继承扩展,甚至有的C#实现方式中直接将单件类前加上了sealed关键字来密封单件类.但是在实际项目中,业务需求的多变必然要求单件类能够被继承.Gof一书中提到了使用注册单件的方法实现单件类的继承.在C#中,我们可以使用继承类扩展单件类,使用反射来根据需求装载不同的单件子类型.
下面是具体的代码示例,示例中演示了C#中单件的一种实现方式和对单件类的继承.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
namespace SingletonDemo
{
class Program{
static void Main(string[] args){
try{
Singleton s1 = Singleton.Instance;
Console.WriteLine("This is {0}.", s1.Name);
Singleton sc = s1.Clone();
Console.WriteLine("This is {0}.", sc.Name);
s1.Name = "小小";
Console.WriteLine("This is {0}.", s1.Name);
Console.WriteLine("This is {0}.", sc.Name);
MySingleton s2 = MySingleton.Instance as MySingleton;
Console.WriteLine("{0} is {1} year old.", s2.Name, s2.Age);
}
catch (Exception ex){
Console.WriteLine("Error:{0}",ex.Message);
}
}
}
public class Singleton{
public string Name = "倪大虾";
//readonly可以保证线程安全
static readonly Singleton instance = Create();
static Singleton(){
}
protected Singleton(){
}
public static Singleton Instance{
get{
return instance;
}
}
private static Singleton Create(){
try{
//从外部(注册表,配置文件...)导入
string typeName = "SingletonDemo.MySingleton";
Type t = Type.GetType(typeName);
ConstructorInfo ci = t.GetConstructor(new Type[]{});
return (Singleton)ci.Invoke(null);
}
catch (Exception ex){
throw ex;
}
}
/*//不能实现克隆方法
public Singleton Clone(){
return new Singleton();
}*/
}
[Serializable]
public class MySingleton:Singleton{
public int Age = 28;
}
}
相关文章推荐
- ps如何将静态图片转化为gif动画图片?
- Service探究
- Android Studio 解决引入java.awt.*以及javax.包问题的一种方法!
- Android四大组件之activity
- hibernate注解配置
- 【mark,备用】串口硬件流量控制说明
- (6) javaweb 文件下载 ie chrome正常 但是ff下载中文名称乱码 另附上传下载代码
- 【Java编程思想】(4)多态
- Hibernate批处理操作优化 (批量插入、更新与删除)
- Hibernate批处理操作优化 (批量插入、更新与删除)
- Hibernate批处理操作优化 (批量插入、更新与删除)
- Hibernate批处理操作优化 (批量插入、更新与删除)
- Hibernate批处理操作优化 (批量插入、更新与删除)
- jquery的父子兄弟节点查找示例代码
- Google发布移动网站设计原则
- 虚函数和纯虚函数
- 黑马程序员----实用的数组排序查找
- 动态生成常用组件
- 冲刺9
- GDI+一般性错误(A generic error occurred in GDI+)