C#C#设计方式:单件(例)情势 — 类也玩计生

那里写的代码,相当于《Head First
设计形式》的读书笔记,原书是java的,自身在上学的进度大校其翻译为C#:

C#,(一)剖析经典的单件格局完结

  单件情势

  – 确定保证三个类唯有三个实例,并提供二个大局访问点

  – 单件格局的类图能够说是有所格局的类图中最不难易行的

  –
有一对对象实际大家只需四个,如线程池、缓存、对话框、处理偏好设置和注册表的指标、日志对象和担任打字与印刷机、显卡等装置的驱动程序的靶子等。借使创设出多少个实例,只怕导致众多题材,如程序的作为10分、财富利用过度,或然结果不平等等

 

  1.新建贰个控制台应用程序:SingletonPattern德姆o。

  2.新建八个类:Singleton.cs

 1 namespace SingletonPatternDemo
 2 {
 3     public class Singleton
 4     {
 5         /// <summary>
 6         /// 利用一个静态变量来记录Singleton类的唯一实例
 7         /// </summary>
 8         private static Singleton _uniqueInstance;
 9 
10         //这里是其它变量...
11 
12         /// <summary>
13         /// 构造器私有化:只能在类内部才能调用构造器
14         /// </summary>
15         private Singleton() { }
16 
17         /// <summary>
18         /// 只能通过该方法获取到对象实例
19         /// </summary>
20         /// <returns></returns>
21         public static Singleton GetInstance()
22         {
23             //【注意】如果我们不需要该实例,它就永远不会产生。这就是“延迟实例化”(lazy instantiaze)
24             return _uniqueInstance ?? (_uniqueInstance = new Singleton());
25 
26             #region 上行相当于以下代码
27             //if (_uniqueInstance == null)
28             //{
29             //    _uniqueInstance = new Singleton();
30             //}
31 
32             //return _uniqueInstance;
33             #endregion
34         }
35 
36         //这里是其它方法...
37     }
38 }

  上边大家去掉注释看看

 1 namespace SingletonPatternDemo
 2 {
 3     public class Singleton
 4     {
 5         private static Singleton _uniqueInstance;
 6 
 7         private Singleton() { }
 8 
 9         public static Singleton GetInstance()
10         {
11             return _uniqueInstance ?? (_uniqueInstance = new Singleton());
12         }
13     }
14 }

  哇塞,这么简单啊!倘使您也这么觉得的话,那就错啦……接下来,大家看下第(二)部分

(二)场景应用

  巧克力工厂

  现代化的巧克力工厂具备计控的巧克力锅炉,锅炉做的事,正是把巧克力和牛奶融在一块儿,然后送到下1个阶段,以构建成巧克力棒。

  那里有3个Choc-O-Holic公司的工业强度巧克力锅炉控制器,用于控制锅炉的家常运转,比如:锅炉内为空时才足以投入原料、锅炉内设有原料并且没有煮沸时才能够进行煮沸,还有排出牛奶和巧克力的混合物时讲求炉内设有已经煮沸的原料等。

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

 1 namespace SingletonPatternDemo
 2 {
 3     /// <summary>
 4     /// 巧克力锅炉
 5     /// </summary>
 6     public class ChocolateBoiler
 7     {
 8         private bool Empty { get; set; }
 9         private bool Boiled { get; set; }
10 
11         //代码开始时,锅炉为空,未燃烧
12         public ChocolateBoiler()
13         {
14             Empty = true;
15             Boiled = false;
16         }
17 
18         /// <summary>
19         /// 填充
20         /// </summary>
21         public void Fill()
22         {
23             //在锅炉内填入原料时,锅炉必须为空;
24             //填入原料后就把两个属性标识好
25             if (Empty)
26             {                
27                 //在锅炉内填满巧克力和牛奶的混合物...
28 
29                 Empty = false;
30                 Boiled = false;
31             }
32         }
33 
34         /// <summary>
35         /// 排出
36         /// </summary>
37         public void Drain()
38         {
39             //锅炉排出时,必须是满的,并且是煮过的;
40             //排出完毕后将Empty标志为true。
41             if (!Empty && Boiled)
42             {
43                 //排出煮沸的巧克力和牛奶...
44 
45                 Empty = true;
46             }
47         }
48 
49         /// <summary>
50         /// 煮沸
51         /// </summary>
52         public void Boil()
53         {
54             //煮混合物时,锅炉必须是满的,并且是没有煮过的;
55             //煮沸后,就把Boiled标识为true。
56             if (!Empty && !Boiled)
57             {
58                 //将炉内物煮沸...
59 
60                 Boiled = true;
61             }
62         }
63     }
64 }

试行依据(一)中所学的剧情将它修改成单例格局

C# 1C# 2

 1 namespace SingletonPatternDemo
 2 {
 3     /// <summary>
 4     /// 巧克力锅炉
 5     /// </summary>
 6     public class ChocolateBoiler
 7     {
 8         private static ChocolateBoiler _uniqueInstance; //【新增】一个静态变量
 9 
10         private bool Empty { get; set; }
11         private bool Boiled { get; set; }
12 
13         //代码开始时,锅炉为空,未燃烧
14         private ChocolateBoiler()   //【修改】原来是public
15         {
16             Empty = true;
17             Boiled = false;
18         }
19 
20         /// <summary>
21         /// 获取ChocolateBoiler对象实例
22         /// </summary>
23         /// <returns></returns>
24         public static ChocolateBoiler GetInstance() //【新增】一个静态方法
25         {
26             return _uniqueInstance ?? (_uniqueInstance = new ChocolateBoiler());
27         }
28 
29         /// <summary>
30         /// 填充
31         /// </summary>
32         public void Fill()
33         {
34             //在锅炉内填入原料时,锅炉必须为空;
35             //填入原料后就把两个属性标识好
36             if (Empty)
37             {                
38                 //在锅炉内填满巧克力和牛奶的混合物...
39 
40                 Empty = false;
41                 Boiled = false;
42             }
43         }
44 
45         /// <summary>
46         /// 排出
47         /// </summary>
48         public void Drain()
49         {
50             //锅炉排出时,必须是满的,并且是煮过的;
51             //排出完毕后将Empty标志为true。
52             if (!Empty && Boiled)
53             {
54                 //排出煮沸的巧克力和牛奶...
55 
56                 Empty = true;
57             }
58         }
59 
60         /// <summary>
61         /// 煮沸
62         /// </summary>
63         public void Boil()
64         {
65             //煮混合物时,锅炉必须是满的,并且是没有煮过的;
66             //煮沸后,就把Boiled标识为true。
67             if (!Empty && !Boiled)
68             {
69                 //将炉内物煮沸...
70 
71                 Boiled = true;
72             }
73         }
74     }
75 }

点击查阅答案

 

【难点】万一而且设有多少个ChocolateBoiler(巧克力锅炉),或者将发出过多倒霉的工作!…
敬请收看第(三)部分

 

(三)处理二十八线程

  现在,只要利用lock,就能够很简短地消除(二)中冒出的难题了

 1 namespace SingletonPatternDemo
 2 {
 3     public class Singleton
 4     {
 5         /// <summary>
 6         /// 利用一个静态变量来记录Singleton类的唯一实例
 7         /// </summary>
 8         private static Singleton _uniqueInstance;
 9 
10         private static readonly object Locker = new object();
11 
12         //这里是其它变量...
13 
14         /// <summary>
15         /// 构造器私有化:只能在类内部才能调用构造器
16         /// </summary>
17         private Singleton() { }
18 
19         /// <summary>
20         /// 只能通过该方法获取到对象实例
21         /// </summary>
22         /// <returns></returns>
23         public static Singleton GetInstance()
24         {
25             //lock:迫使每个线程在进入该方法之前,需要等候别的线程离开该方法,
26             //  也就是说,不会有两个线程可以同时进入该方法
27             lock (Locker)
28             {
29                 if (_uniqueInstance == null)
30                 {
31                     //【注意】如果我们不需要该实例,它就永远不会产生。这就是“延迟实例化”(lazy instantiaze)
32                     _uniqueInstance = new Singleton();
33                 }
34             }
35             
36 
37             return _uniqueInstance;
38 
39         }
40 
41         //这里是其它方法...
42     }
43 }

  可是,现在又出新了品质的难点!…

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

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

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

 1 namespace SingletonPatternDemo
 2 {
 3     public class Singleton
 4     {
 5         private static Singleton _uniqueInstance;
 6         private static readonly object Locker = new object();
 7 
 8         private Singleton() { }
 9 
10         public static Singleton GetInstance()
11         {
12             //检查实例,如果不存在,就进入同步区块
13             if (_uniqueInstance == null)
14             {
15                 lock (Locker)
16                 {
17                     if (_uniqueInstance == null)
18                     {
19                         //只有第一次才彻底执行这里的代码
20                         _uniqueInstance = new Singleton();
21                     }
22                 }
23             }                     
24 
25             return _uniqueInstance;
26         }
27 
28     }
29 }

  完毕… …

相关文章