如众所知,单件模式做为<Gof 23中设计模式>之一,其意图仅允许单件类的一个实例存在(扩展单件模式不在此文范围内),并提供全局的访问方法.UML类图如下.

http://csharpindepth.com/Articles/General/Singleton.aspx一文中列举了单件模式实现的5种方法,但诸多文章中都或多或少的遗漏一些问题:如何保证线程安全,如何保证仅有一个实例存在,如何根据业务变化扩展.

下面以C#实现单件为例,对这些问题一一说明.

  1. 1.         如何保证线程安全

在C#中可以使用static,readonly两个关键字保证单件的线程安全.static关键字修饰的静态成员在程序运行时由 .NET Framework 公共语言运行库 (CLR) 自动加载管理,这些成员是密封的,全局的,且不能被实例化。诸如此类的特点,让C#中的单件实现更加方便简洁.readonly关键字可用于保证对单件实例的引用在任何情况下不被修改.也因此与static一起保证单件的线程安全.

  1. 2.         如何保证仅有一个实例存在

在C#中,static关键字保证了对单件实例的唯一引用,隐藏构造函数保证无法通过new构造对象.但这并不能保证单件实例的唯一性.如我们可以反序列化出一个单件类型的实例,也可以通过实现克隆接口克隆一个单件的实例.

因此我们要保证单件类型不能被序列化,不能被克隆,即不能为单件类型及扩展类型添加Serializable标签和实现克隆接口或方法.

  1. 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;
    }
}

最新文章

  1. DDD:谈谈数据模型、领域模型、视图模型和命令模型
  2. 最新app store 应用提交经验分享
  3. NOSQL Mongo入门学习笔记 - MongoDB的安装(一)
  4. Retrofit – Java(Android) 的REST 接口封装类库
  5. HTML增加删除邮件(table)
  6. 字符串匹配算法——KMP、BM、Sunday
  7. VS2012(update3)编译Qt5.1.1 32位静态库debug-and-release版及结果分享
  8. 【稳定婚姻问题】【HDU1435】【Stable Match】
  9. winform 实现选择的城市名单
  10. python编码问题之\&quot;encode\&quot;&amp;\&quot;decode\&quot;
  11. CXF 开发 REST 服务
  12. 云+社区分享——腾讯云OCR文字识别
  13. was cached in the local repository, resolution will not be reattempted until the update interval of fintech has elapsed or updates are forced
  14. Python内置函数(38)——list
  15. 浅谈Java简单实现的生产者与消费者问题
  16. synchronized (string.intern())
  17. 今日面试WPS总结
  18. html学习代码
  19. VisualStudio 发布代码的一个坑
  20. Python学习笔记 - day7 - 类

热门文章

  1. Oracle统计每条数据的大小
  2. JS判断设备类型跳转至PC端或移动端相应页面
  3. 续:纠正:ubuntu 【6.04 LTS】可以安装安装 ! for《Oracle-10.2.0.1,打补丁10.2.0.5:在 debian 版本4【不含4】以上,及 ubuntu 7.04【不含7.04】以上都可以安装!》
  4. 代码记录——phase16,block36
  5. zabbix-agents客户端安装
  6. Windows程序执行过程
  7. Ubuntu Git安装与使用
  8. Maven update project...后jdk变成1.5,update project后jdk版本改变
  9. 【代码审计】CLTPHP_v5.5.3前台XML外部实体注入漏洞分析
  10. sharepoint权限操作(记录以备忘)