这里写的代码,相当于《Head First 设计模式》的读书笔记,原书是java的,自己在学习的过程中将其翻译为C#:

(一)剖析经典的单件模式实现

  单件模式

  -- 确保一个类只有一个实例,并提供一个全局访问点

  -- 单件模式的类图可以说是所有模式的类图中最简单的

  -- 有一些对象其实我们只需一个,如线程池、缓存、对话框、处理偏好设置和注册表的对象、日志对象和充当打印机、显卡等设备的驱动程序的对象等。如果制造出多个实例,可能导致许多问题,如程序的行为异常、资源使用过度,或者结果不一致等

  1.新建一个控制台应用程序:SingletonPatternDemo。

  2.新建一个类:Singleton.cs

 namespace SingletonPatternDemo
{
public class Singleton
{
/// <summary>
/// 利用一个静态变量来记录Singleton类的唯一实例
/// </summary>
private static Singleton _uniqueInstance; //这里是其它变量... /// <summary>
/// 构造器私有化:只能在类内部才能调用构造器
/// </summary>
private Singleton() { } /// <summary>
/// 只能通过该方法获取到对象实例
/// </summary>
/// <returns></returns>
public static Singleton GetInstance()
{
//【注意】如果我们不需要该实例,它就永远不会产生。这就是“延迟实例化”(lazy instantiaze)
return _uniqueInstance ?? (_uniqueInstance = new Singleton()); #region 上行相当于以下代码
//if (_uniqueInstance == null)
//{
// _uniqueInstance = new Singleton();
//} //return _uniqueInstance;
#endregion
} //这里是其它方法...
}
}

  下面我们去掉注释看看

 namespace SingletonPatternDemo
{
public class Singleton
{
private static Singleton _uniqueInstance; private Singleton() { } public static Singleton GetInstance()
{
return _uniqueInstance ?? (_uniqueInstance = new Singleton());
}
}
}

  哇塞,这么简单啊!如果你也这么认为的话,那就错啦......接下来,我们看下第(二)部分

(二)场景应用

  巧克力工厂

  现代化的巧克力工厂具备计算机控制的巧克力锅炉,锅炉做的事,就是把巧克力和牛奶融在一起,然后送到下一个阶段,以制造成巧克力棒。

  这里有一个Choc-O-Holic公司的工业强度巧克力锅炉控制器,用于控制锅炉的日常运作,比如:锅炉内为空时才可以加入原料、锅炉内存在原料并且尚未煮沸时才能够进行煮沸,还有排出牛奶和巧克力的混合物时要求炉内存在已经煮沸的原料等。

  下列是巧克力锅炉控制器的代码:

 namespace SingletonPatternDemo
{
/// <summary>
/// 巧克力锅炉
/// </summary>
public class ChocolateBoiler
{
private bool Empty { get; set; }
private bool Boiled { get; set; } //代码开始时,锅炉为空,未燃烧
public ChocolateBoiler()
{
Empty = true;
Boiled = false;
} /// <summary>
/// 填充
/// </summary>
public void Fill()
{
//在锅炉内填入原料时,锅炉必须为空;
//填入原料后就把两个属性标识好
if (Empty)
{
//在锅炉内填满巧克力和牛奶的混合物... Empty = false;
Boiled = false;
}
} /// <summary>
/// 排出
/// </summary>
public void Drain()
{
//锅炉排出时,必须是满的,并且是煮过的;
//排出完毕后将Empty标志为true。
if (!Empty && Boiled)
{
//排出煮沸的巧克力和牛奶... Empty = true;
}
} /// <summary>
/// 煮沸
/// </summary>
public void Boil()
{
//煮混合物时,锅炉必须是满的,并且是没有煮过的;
//煮沸后,就把Boiled标识为true。
if (!Empty && !Boiled)
{
//将炉内物煮沸... Boiled = true;
}
}
}
}

试试根据(一)中所学的内容将它修改成单例模式

 namespace SingletonPatternDemo
{
/// <summary>
/// 巧克力锅炉
/// </summary>
public class ChocolateBoiler
{
private static ChocolateBoiler _uniqueInstance; //【新增】一个静态变量 private bool Empty { get; set; }
private bool Boiled { get; set; } //代码开始时,锅炉为空,未燃烧
private ChocolateBoiler() //【修改】原来是public
{
Empty = true;
Boiled = false;
} /// <summary>
/// 获取ChocolateBoiler对象实例
/// </summary>
/// <returns></returns>
public static ChocolateBoiler GetInstance() //【新增】一个静态方法
{
return _uniqueInstance ?? (_uniqueInstance = new ChocolateBoiler());
} /// <summary>
/// 填充
/// </summary>
public void Fill()
{
//在锅炉内填入原料时,锅炉必须为空;
//填入原料后就把两个属性标识好
if (Empty)
{
//在锅炉内填满巧克力和牛奶的混合物... Empty = false;
Boiled = false;
}
} /// <summary>
/// 排出
/// </summary>
public void Drain()
{
//锅炉排出时,必须是满的,并且是煮过的;
//排出完毕后将Empty标志为true。
if (!Empty && Boiled)
{
//排出煮沸的巧克力和牛奶... Empty = true;
}
} /// <summary>
/// 煮沸
/// </summary>
public void Boil()
{
//煮混合物时,锅炉必须是满的,并且是没有煮过的;
//煮沸后,就把Boiled标识为true。
if (!Empty && !Boiled)
{
//将炉内物煮沸... Boiled = true;
}
}
}
}

点击查看答案

【问题】万一同时存在多个ChocolateBoiler(巧克力锅炉),可能将发生很多糟糕的事情!... 敬请收看第(三)部分

(三)处理多线程

  现在,只要使用lock,就可以很简单地解决(二)中出现的问题了

 namespace SingletonPatternDemo
{
public class Singleton
{
/// <summary>
/// 利用一个静态变量来记录Singleton类的唯一实例
/// </summary>
private static Singleton _uniqueInstance; private static readonly object Locker = new object(); //这里是其它变量... /// <summary>
/// 构造器私有化:只能在类内部才能调用构造器
/// </summary>
private Singleton() { } /// <summary>
/// 只能通过该方法获取到对象实例
/// </summary>
/// <returns></returns>
public static Singleton GetInstance()
{
//lock:迫使每个线程在进入该方法之前,需要等候别的线程离开该方法,
// 也就是说,不会有两个线程可以同时进入该方法
lock (Locker)
{
if (_uniqueInstance == null)
{
//【注意】如果我们不需要该实例,它就永远不会产生。这就是“延迟实例化”(lazy instantiaze)
_uniqueInstance = new Singleton();
}
} return _uniqueInstance; } //这里是其它方法...
}
}

  但是,现在又出现了性能的问题!...

  方案一:使用“急切”创建实例,而不用延迟实例化的做法

 namespace SingletonPatternDemo
{
public class Singleton
{
//如果应用程序总是创建并使用单件实例,或者在创建和运行时方面的负担不太繁重,可以选择这种方法 //在静态初始化器中创建单件,这段代码保证了线程安全
private static readonly Singleton UniqueInstance = new Singleton(); private Singleton() { } public static Singleton GetInstance()
{
return UniqueInstance;
}
}
}

  方案二:用“双重检查加锁”

 namespace SingletonPatternDemo
{
public class Singleton
{
private static Singleton _uniqueInstance;
private static readonly object Locker = new object(); private Singleton() { } public static Singleton GetInstance()
{
//检查实例,如果不存在,就进入同步区块
if (_uniqueInstance == null)
{
lock (Locker)
{
if (_uniqueInstance == null)
{
//只有第一次才彻底执行这里的代码
_uniqueInstance = new Singleton();
}
}
} return _uniqueInstance;
} }
}

  完毕... ...

C#设计模式:单件(例)模式 -- 类也玩计划生育的更多相关文章

  1. java设计模式3--单例模式(Singleton)

    本文地址:http://www.cnblogs.com/archimedes/p/java-singleton-pattern.html,转载请注明源地址. 单例模式 保证一个类仅有一个实例,并提供一 ...

  2. 24种设计模式--多例模式【Multition Pattern】

    这种情况有没有?有!大点声,有没有?有,是,确实有,就出现在明朝,那三国期间的算不算,不算,各自称帝,各有各的地盘,国号不同.大家还 记得那首诗<石灰吟>吗?作者是谁?于谦,他是被谁杀死的 ...

  3. java设计模式——多例模式

    ★ 缓存在单例中的使用    缓存在编程中使用很频繁,有着非常重要的作用,它能够帮助程序实现以空间换取时间,通 常被设计成整个应用程序所共享的一个空间,现要求实现一个用缓存存放单例对象的类. 说明:该 ...

  4. 设计模式1---单例模式(Singleton pattern)

    单例模式Singleton 面试的时候,问到许多年轻的Android开发他所会的设计模式是什么,基本上都会提到单例模式,但是对 单例模式也是一知半解,在Android开发中我们经常会运用单例模式,所以 ...

  5. java设计模式1--单例模式

    1:单例模式简介 单例模式是一种常用的软件设计模式,它确保某个类只有一个实例,而且自行实例化并向整个系统提供唯一的实例.总而言之就是在系统中只会存在一个对象,其中的数据是共享的 特点: 单例类只能有一 ...

  6. JS设计模式1-单例模式

    单例模式是一种常用的模式,有一些对象我们往往只需要一个,比如全局缓存,window对象.单例模式在js开发中单例模式的用途非常广泛,比如页面中有一个登录浮窗,无论单击多少次登录窗口,这个窗口只会创建一 ...

  7. [java]设计模式1-单例模式

    单例模式:单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例.在计算机系统中,线程池.缓存.日志对象.对话框.打印机.显卡的驱动程序对象常被设计成单例.这些应用都或多或少具有资源管 ...

  8. javascript 设计模式1----单例模式

    定义:保证一个类仅有一个实例,并提供一个访问的全局接口: 就是收:当我们 var a = new a(); var a1 = new a()是:a与a1是相等的.怎么实现呢,就是第一次实例化.第二不在 ...

  9. 设计模式java----单例模式

    一.懒汉式单例 在第一次调用的时候实例化自己,Singleton的唯一实例只能通过getInstance()方法访问.线程不安全 /** * Created by Admin on 2017/3/19 ...

随机推荐

  1. js-静态、原型、实例属性

    本篇来说一下js中的属性: 1.静态属性 2.原型属性 3.实例属性 静态属性: function klass(){} var obj=new klass(); klass.count=0; klas ...

  2. load和initialize方法

      一.load 方法什么时候调用: 在main方法还没执行的时候 就会 加载所有类,调用所有类的load方法. load方法是线程安全的,它使用了锁,我们应该避免线程阻塞在load方法. 在项目中使 ...

  3. nginx源码分析之模块初始化

    在nginx启动过程中,模块的初始化是整个启动过程中的重要部分,而且了解了模块初始化的过程对应后面具体分析各个模块会有事半功倍的效果.在我看来,分析源码来了解模块的初始化是最直接不过的了,所以下面主要 ...

  4. AbpZero--2.如何启动

    1.直接启动 VS中直接启动 2.IIS站点 IIS中配置一个站点来启动(推荐) 3.登录 系统默认创建2个用户 默认用户名:admin 密码:123qwe 租户:Default  默认用户名:adm ...

  5. unity 3d 解析 json

    官网案例传送门 我这里不过是借花献佛,案例官网就有. using UnityEngine; using System.Collections; public class json : MonoBeha ...

  6. MVC还是MVVM?或许VMVC更适合WinForm客户端

    最近开始重构一个稍嫌古老的C/S项目,原先采用的技术栈是『WinForm』+『WCF』+『EF』.相对于现在铺天盖地的B/S架构来说,看上去似乎和Win95一样古老,很多新入行的,可能就没有见过经典的 ...

  7. ABP文档翻译--值对象

    本人是ABP初学者,在看英文文档和@tkb至简 的ABP框架理论研究总结(典藏版)时,发现大神@tkb至简中少了对Value Objects的翻译,看文档是新的,大神没时间把,小弟给补充上. 介绍 值 ...

  8. js刷新页面方法大全

    如何实现刷新当前页面呢?借助js你将无所不能. 1,reload 方法,该方法强迫浏览器刷新当前页面.语法:location.reload([bForceGet])   参数: bForceGet, ...

  9. BPM的魅力何在?

    BPM(Business Process Management , 企业流程管理平台) 是带动企业流程自动化的帮 手,也是最能忠实反应出企业作业流程问题症结的系统工具,在管理上,BPM可以让管理者利用 ...

  10. 对Maven、gradle、svn、spring 3.0 fragment、git的想法

    1.Maven Maven可以构建项目,采用pom方式配置主项目和其他需要引用的项目.同时可结合spring3.0的新特性web  fragment. 从现实出发,特别是对于管理不到位,程序员整体素质 ...