如众所知,单件模式做为<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;
    }
}

NET中的设计模式---单件模式的更多相关文章

  1. [Head First设计模式]饺子馆(冬至)中的设计模式——工厂模式

    系列文章 [Head First设计模式]山西面馆中的设计模式——装饰者模式 [Head First设计模式]山西面馆中的设计模式——观察者模式 [Head First设计模式]山西面馆中的设计模式— ...

  2. [Head First设计模式]抢票中的设计模式——代理模式

    系列文章 [Head First设计模式]山西面馆中的设计模式——装饰者模式 [Head First设计模式]山西面馆中的设计模式——观察者模式 [Head First设计模式]山西面馆中的设计模式— ...

  3. [Head First设计模式]餐馆中的设计模式——命令模式

    系列文章 [Head First设计模式]山西面馆中的设计模式——装饰者模式 [Head First设计模式]山西面馆中的设计模式——观察者模式 [Head First设计模式]山西面馆中的设计模式— ...

  4. [转] Android中的设计模式-备忘录模式

    转自Android中的设计模式-备忘录模式 定义 备忘录设计模式的定义就是把对象的状态记录和管理委托给外界处理,用以维持自己的封闭性. 比较官方的定义 备忘录模式(Memento Pattern)又叫 ...

  5. 【转】Struts2的线程安全 和Struts2中的设计模式----ThreadLocal模式

    [转]Struts2的线程安全 和Struts2中的设计模式----ThreadLocal模式 博客分类: 企业应用面临的问题 java并发编程 Struts2的线程安全ThreadLocal模式St ...

  6. C#设计模式——单件模式

    一.为何需要单件模式 需求 我们开发了一个大型的项目,其中存在许多的工具类.但是其中很多的工具类我们并不是经常使用得到,甚至 一次都不会使用.但是这些工具类都是静态的类,会消耗很多的内存,即使一次都不 ...

  7. [Head First设计模式]山西面馆中的设计模式——建造者模式

    系列文章 [Head First设计模式]山西面馆中的设计模式——装饰者模式 [Head First设计模式]山西面馆中的设计模式——观察者模式 引言 将学习融入生活中,是件很happy的事情,不会感 ...

  8. C#设计模式——单件模式(Singleton Pattern)

    一.概述在软件开发过程中,我们有时候需要保证一个类仅有一个实例,比如在一个电脑用户下只能运行一个outlook实例.这时就需要用到单件模式.二.单件模式单件模式保证一个类仅有一个实例,并提供一个访问它 ...

  9. 说说设计模式~单件模式(Singleton)

    单件模式(Singleton)要求一个类有且仅有一个实例,并且提供了一个全局的访问点. 从概念上来研究一下它的实现,不考虑线程安全 1 public sealed class Singlton 2 { ...

随机推荐

  1. 安卓开发笔记——ListView加载性能优化ViewHolder

    在前不久做安卓项目的时候,其中有个功能是爬取某网站上的新闻信息,用ListView展示,虽然做了分页,但还是觉得达不到理想流畅效果. 上网查阅了些资料,发现一些挺不错的总结,这里记录下,便于复习. 当 ...

  2. DWZ主从表界面唯一性验证(自写js)(一)

    最近在项目中遇到一个问题,它的需求是: 利用DWZ的主从表结构批量添加课程信息,需要在触发课程代码文本框的离开事件时验证: 1.是否选择学院. 2.数据库里是否已存在该课程代码. 3.多条数据添加时, ...

  3. jenkins 神奇变量

    Hudson自己设置的一些环境变量可用于通过Hudson来执行shell脚本.Windows批处理文件和Ant文件,他们包括 Hudson设置环境变量 当一个Hudson作业执行时,它会设置一些环境变 ...

  4. UITextField in a UITableViewCell

    http://stackoverflow.com/questions/409259/having-a-uitextfield-in-a-uitableviewcell http://stackover ...

  5. scala函数demo

    /** * Created by root * Description : 柯里化函数,偏应用函数,匿名函数,高阶函数 */ object FunctionTest { def main(args: ...

  6. fstream 和 iostream

    fstream 是对文件输入输出iostream是对屏幕上输入输出你想往文件里保存内容,或者从文件里读取内容就用fstream向屏幕输出或者从屏幕上输入,用iostream “>>”运算符 ...

  7. Qt生成ui文件对应的.h和.cpp文件

    在VS中,可以通过CMake设定QT5_WRAP_UI来编译a.ui到ui_a.h, 要想快速生成a.h和a.cpp,经过尝试,必须使用Qt Creator,否则就手写.

  8. 一个简单的demo学习Android远程Service(AIDL的使用)

    这是milo很早之前写在论坛上的一个帖子,现在整理出来,milo也复习一下一般来说Android 的四大组件都是运行在同一个进程中的,但远程Service运行在不同的进程里.这进程间的通信是使用了An ...

  9. Pycharm按装

    1.python 官方 2.下载完成后点击exe 安装 3.按装完成后在cmd中输入 python 1.如果显示python版本 那么就安装成功 2.如果出现"python"不是外 ...

  10. js同步 异步 运行机制

    需要知道的那些事: 1.JS是单线程的(为什么?因为能提高效率.作为浏览器脚本语言,js的主要用途是与用户互动,操作DOM.而这也就决定它只能为单线程,否则会带来很复杂的同步问题),也就是说无法同时执 ...