首页 / C# / 单例模式(C#实现)
单例模式(C#实现)
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了单例模式(C#实现),小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含7936字,纯文字阅读大概需要12分钟。
内容图文
![单例模式(C#实现)](/upload/InfoBanner/zyjiaocheng/1322/e8b9dbcd664c4f9583f908d06736978c.jpg)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
|
这是这段时间学习设计模式的时候的源代码。
单例(单件)模式的五种实现。
通过一个计数器的例子调用验证一下。
把下面的代码直接拷进vs下,运行就可以了。(控制台应用程序)
以后把剩余的设计模式有空儿就粘上来。
[csharp] view plaincopy
using
System;
using
System.Collections.Generic;
using
System.Text;
using
System.Threading;
namespace
NetFarmwork
{
class
NetFarmwork
{
static
void
Main(
string
[] args)
{
Thread thread0 = Thread.CurrentThread;
thread0.Name =
"Thread 0"
;
Thread thread1 =
new
Thread(
new
ThreadStart(SigletonPattern.SigletonCounter.CountMutilThread.DoSomeWork));
thread1.Name =
"Thread 1"
;
Thread thread2 =
new
Thread(
new
ThreadStart(SigletonPattern.SigletonCounter.CountMutilThread.DoSomeWork));
thread2.Name =
"Thread 2"
;
Thread thread3 =
new
Thread(
new
ThreadStart(SigletonPattern.SigletonCounter.CountMutilThread.DoSomeWork));
thread3.Name =
"Thread 3"
;
thread1.Start();
thread2.Start();
thread3.Start();
//线程0也只执行和其他线程相同的工作
SigletonPattern.SigletonCounter.CountMutilThread.DoSomeWork();
Console.ReadKey();
}
}
[csharp] view plaincopy
#region 单例模式
#region 用法说明
//保证一个类仅有一个实例,并提供一个访问它的全局访问点
// 实现要点
// Singleton模式是限制而不是改进类的创建。
// Singleton类中的实例构造器可以设置为Protected以允许子类派生。
// Singleton模式一般不要支持Icloneable接口,因为这可能导致多个对象实例,与Singleton模式的初衷违背。
// Singleton模式一般不要支持序列化,这也有可能导致多个对象实例,这也与Singleton模式的初衷违背。
// Singleton只考虑了对象创建的管理,没有考虑到销毁的管理,就支持垃圾回收的平台和对象的开销来讲,我们一般没必要对其销毁进行特殊的管理。
// 理解和扩展Singleton模式的核心是“如何控制用户使用new对一个类的构造器的任意调用”。
// 可以很简单的修改一个Singleton,使它有少数几个实例,这样做是允许的而且是有意义的。
//优点
// 实例控制:Singleton 会阻止其他对象实例化其自己的 Singleton 对象的副本,从而确保所有对象都访问唯一实例
// 灵活性:因为类控制了实例化过程,所以类可以更加灵活修改实例化过程
//缺点
// 开销:虽然数量很少,但如果每次对象请求引用时都要检查是否存在类的实例,将仍然需要一些开销。可以通过使用静态初始化解决此问题,上面的五种实现方式中已经说过了。
// 可能的开发混淆:使用 singleton 对象(尤其在类库中定义的对象)时,开发人员必须记住自己不能使用 new 关键字实例化对象。因为可能无法访问库源代码,因此应用程序开发人员可能会意外发现自己无法直接实例化此类。
// 对象的生存期:Singleton 不能解决删除单个对象的问题。在提供内存管理的语言中(例如基于 .NET Framework 的语言),只有 Singleton 类能够导致实例被取消分配,因为它包含对该实例的私有引用。在某些语言中(如 C++),其他类可以删除
//对象实例,但这样会导致 Singleton 类中出现悬浮引用。
//适用性
// 当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时。
// 当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。
//应用场景
// 每台计算机可以有若干个打印机,但只能有一个Printer Spooler,避免两个打印作业同时输出到打印机。
//(摘自吕震宇的C#设计模式(7)-Singleton Pattern)
// PC机中可能有几个串口,但只能有一个COM1口的实例。
// 系统中只能有一个窗口管理器。
// .NET Remoting中服务器激活对象中的Sigleton对象,确保所有的客户程序的请求都只有一个实例来处理。
#endregion
[csharp] view plaincopy
//共有五种实现方案
/// <summary>
/// 简单实现
/// 类声明中使用sealed可防止其它类继承此类
/// 私有构造函数禁止实例化该类
///
/// 缺点:这种方式的实现对于线程来说并不是安全的,因为在多线程的环境下有可能得到Singleton类的多个实例。如果同时有两个线程去判断(instance == null),并且得到的结果为真,这时两个线程都会创建类Singleton的实例,这样就违背了Singleton模式的原则。实际上在上述代码中,有可能在计算出表达式的值之前,对象实例已经被创建,但是内存模型并不能保证对象实例在第二个线程创建之前被发现
/// 优点:
/// 由于实例是在 Instance 属性方法内部创建的,因此类可以使用附加功能(例如,对子类进行实例化),即使它可能引入不想要的依赖性。
/// 直到对象要求产生一个实例才执行实例化;这种方法称为“惰性实例化”。惰性实例化避免了在应用程序启动时实例化不必要的 singleton。
/// </summary>
public
sealed
class
Singleton
{
private
static
Singleton instance =
null
;
private
Singleton(){}
public
static
Singleton Instance
{
get
{
if
(instance ==
null
)
{
instance =
new
Singleton();
}
return
instance;
}
}
}
/// <summary>
/// 安全的线程
///
/// lock 关键字可以用来确保代码块完成运行,而不会被其他线程中断。这是通过在代码块运行期间为给定对象获取互斥锁来实现的。
/// lock 语句以关键字 lock 开头,它有一个作为参数的对象,在该参数的后面还有一个一次只能由一个线程执行的代码块。
/// 提供给 lock 关键字的参数必须为基于引用类型的对象,该对象用来定义锁的范围。
///
/// 这种方式的实现对于线程来说是安全的。我们首先创建了一个进程辅助对象,线程在进入时先对辅助对象加锁然后再检测对象是否被创建,这样可以确保只有一个实例被创建,因为在同一个时刻加了锁的那部分程序只有一个线程可以进入。这种情况下,对象实例由最先进入的那个线程创建,后来的线程在进入时(instence == null)为假,不会再去创建对象实例了。但是这种实现方式增加了额外的开销,损失了性能。
/// </summary>
public
sealed
class
Singleton2
{
private
static
Singleton2 instance =
null
;
private
static
readonly
object
padlock =
new
object
();
private
Singleton2() { }
public
static
Singleton2 Instance
{
get
{
lock
(padlock)
{
if
(instance ==
null
)
{
instance =
new
Singleton2();
}
return
instance;
}
}
}
}
/// <summary>
/// 双重锁定
///
/// 这种实现方式对多线程来说是安全的,同时线程不是每次都加锁,只有判断对象实例没有被创建时它才加锁,有了我们上面第一部分的里面的分析,我们知道,加锁后还得再进行对象是否已被创建的判断。它解决了线程并发问题,同时避免在每个 Instance 属性方法的调用中都出现独占锁定。它还允许您将实例化延迟到第一次访问对象时发生。实际上,应用程序很少需要这种类型的实现。大多数情况下我们会用静态初始化。这种方式仍然有很多缺点:无法实现延迟初始化。
/// </summary>
public
sealed
class
Singleton3
{
private
static
Singleton3 instance =
null
;
private
static
readonly
object
padlock =
new
object
();
private
Singleton3() { }
public
static
Singleton3 Instance
{
get
{
if
(instance ==
null
)
{
lock
(padlock)
{
if
(instance ==
null
)
{
instance =
new
Singleton3();
}
}
}
return
instance;
}
}
}
/// <summary>
/// 静态初始化
/// 在大多数情况下,静态初始化是在 .NET 中实现 Singleton 的首选方法。
/// 该类标记为 sealed 以阻止发生派生,而派生可能会增加实例。此外,变量标记为 readonly,这意味着只能在静态初始化期间(此处显示的示例)或在类构造函数中分配变量。
///
/// 该实现与前面的示例类似,不同之处在于它依赖公共语言运行库来初始化变量。它仍然可以用来解决 Singleton 模式试图解决的两个基本问题:全局访问和实例化控制。公共静态属性为访问实例提供了一个全局访问点。此外,由于构造函数是私有的,因此不能在类本身以外实例化 Singleton 类;因此,变量引用的是可以在系统中存在的唯一的实例。 由于 Singleton 实例被私有静态成员变量引用,因此在类首次被对 Instance 属性的调用所引用之前,不会发生实例化。
/// 这种方法唯一的潜在缺点是,您对实例化机制的控制权较少。在 Design Patterns 形式中,您能够在实例化之前使用非默认的构造函数或执行其他任务。由于在此解决方案中由 .NET Framework 负责执行初始化,因此您没有这些选项。在大多数情况下,静态初始化是在 .NET 中实现 Singleton 的首选方法。
/// </summary>
public
sealed
class
Singleton4
{
private
static
readonly
Singleton4 instance =
new
Singleton4();
static
Singleton4() { }
private
Singleton4() { }
public
static
Singleton4 Instance
{
get
{
return
instance;
}
}
}
/// <summary>
/// 延迟初始化
/// 类声明了internal后只对整个项目可见,虽然其成员可以是public声明的,但因类只在当前项目中可见,所以其成员也就只能在当前项目访问了。
///
/// 这里,初始化工作有Nested类的一个静态成员来完成,这样就实现了延迟初始化,并具有很多的优势,是值得推荐的一种实现方式
/// </summary>
public
sealed
class
Singleton5
{
private
Singleton5() { }
public
static
Singleton5 Instance
{
get
{
return
Nested.instance;
}
}
private
class
Nested
{
static
Nested() { }
internal
static
readonly
Singleton5 instance =
new
Singleton5();
}
}
#endregion
}
#region 单例模式测试示例
namespace
SigletonPattern.SigletonCounter
{
using
System;
using
System.Threading;
/// <summary>
/// 功能:简单计数器的单件模式
/// 日期:2009年8月19日
/// </summary>
public
class
CountSigleton
{
//存储唯一的实例
private
static
CountSigleton uniCounter =
new
CountSigleton();
//存储计数值
private
int
totalNum = 0;
private
CountSigleton()
{
//线程延迟2000毫秒
Thread.Sleep(2000);
}
public
static
CountSigleton Instance()
{
return
uniCounter;
}
//计数加1
public
void
Add()
{
totalNum++;
}
//获得当前计数值
public
int
GetCounter()
{
return
totalNum;
}
}
}
namespace
SigletonPattern.SigletonCounter
{
using
System;
using
System.Threading;
using
System.Text;
/// <summary>
/// 功能:创建一个多线程计数的类
/// 日期:2009年8月19日
/// </summary>
public
class
CountMutilThread
{
public
CountMutilThread()
{ }
public
static
void
DoSomeWork()
{
//构造显示字符串
string
results =
""
;
//创建一个Sigleton实例
CountSigleton MyCounter = CountSigleton.Instance();
//循环调用四次(四个线程循环执行四次,即MyCounter.Add()了十六次,最终的结果是计数器最大为16)
for
(
int
i = 1; i < 5; i++)
{
MyCounter.Add();
results +=
"线程"
;
results += Thread.CurrentThread.Name.ToString() +
"——>"
;
results +=
"当前的计数:"
;
results += MyCounter.GetCounter().ToString();
results +=
"\n"
;
Console.WriteLine(results);
//清空显示字符串
results =
""
;
}
}
}
}
#endregion
|
原文:http://www.cnblogs.com/fhlj/p/3613682.html
内容总结
以上是互联网集市为您收集整理的单例模式(C#实现)全部内容,希望文章能够帮你解决单例模式(C#实现)所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。