C# · 12月 20, 2021

C#设计模式:单件(例)模式 — 类也玩计划生育

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

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

  

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

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

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

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

  2.新建一个类:Singleton.cs

如果我们不需要该实例,它就永远不会产生。这就是“延迟实例化”(lazy instantiaze) _uniqueInstance ?? (_uniqueInstance = 上行相当于以下代码 }

  下面我们去掉注释看看

_uniqueInstance ?? (_uniqueInstance = }

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

(二)场景应用

  巧克力工厂

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

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

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

Empty { ; Boiled { ; Empty = Boiled = Empty = Boiled = (!Empty && Empty = (!Empty && ! Boiled = }

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

ChocolateBoiler _uniqueInstance; Empty { ; Boiled { ; ChocolateBoiler() Empty = Boiled = ChocolateBoiler GetInstance() _uniqueInstance ?? (_uniqueInstance = Empty = Boiled = (!Empty && Empty = (!Empty && ! Boiled = }

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

(三)处理多线程

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

Locker = (_uniqueInstance == _uniqueInstance = }

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

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

Singleton UniqueInstance = }

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

Locker = (_uniqueInstance == (_uniqueInstance == _uniqueInstance = }

  完毕… …