注册
|
登录
发帖
热搜
活动
交友
discuz
论坛
BBS
翼度工具
翼度网址导航
开发工具
Linux命令速查
网页设计配色表
在线制作icon
颜色代码选取器
翼度科技
»
论坛
›
编程开发
›
.net
›
查看内容
返回列表
发新帖
【23种设计模式】单例模式(一)
致我逝去的青春
致我逝去的青春
当前离线
积分
30
10
主题
10
帖子
30
积分
新手上路
新手上路, 积分 30, 距离下一级还需 20 积分
新手上路, 积分 30, 距离下一级还需 20 积分
积分
30
发消息
显示全部楼层
前言:
单例模式是创建型模式5种中的第1种,
关注对象的创建, 保证一个类仅有一个实例,并且提供一个全局访问点
。在软件系统中,经常有这样一些特殊的类,必须保证它们在系统中只存在一个实例,才能确保它们的逻辑正确性、以及良好的效率。如何绕过常规的构造器,提供一种机制来保证一个类只创建一个实例?
一、应用场景:
要求生产唯一序列号。
WEB 中的计数器,比如不用每次刷新都在数据库里加一次,用单例先缓存起来。
创建的多个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。
二、创建与实现:
以下提供两种情景实现方式,分别是单线程访问和多线程访问:
单线程实现:
定义:
public class SingleObject
{
#region 第一种写法
/// <summary>
/// 创建 SingleObject 的一个对象
/// </summary>
private static SingleObject instance = new SingleObject();
/// <summary>
/// 让构造函数为 private,这样该类就不会被实例化
/// </summary>
private SingleObject() { }
/// <summary>
/// 获取全局唯一对象
/// </summary>
/// <returns></returns>
public static SingleObject getInstance()
{
return instance;
}
#endregion
#region 另外一种写法
/// <summary>
/// 创建 SingleObject 的一个空对象
/// </summary>
private static SingleObject instance2 = null;
/// <summary>
/// 获取全局唯一对象
/// </summary>
public static SingleObject getInstance2
{
get
{
if (instance == null)
{
instance = new SingleObject();
}
return instance2;
}
}
#endregion
/// <summary>
/// 单例中定义的方法
/// </summary>
/// <returns></returns>
public string showMessage()
{
return "这是单例设计模式返回的信息....";
}
}
复制代码
全局单例访问:
//不合法的构造函数
//编译时错误:构造函数 SingleObject() 是不可见的
//SingleObject object = new SingleObject();
/// <summary>
/// 获取唯一可用的对象
/// </summary>
SingleObject object = SingleObject.getInstance();
/// <summary>
/// 调用返回消息
/// </summary>
string str = object.showMessage();
复制代码
说明:
以上代码在单线程情况下不会出现任何问题。但是在多线程的情况下却不是安全的。如两个线程同时运行到:
if (instance == null)
复制代码
判断是否被实例化,一个线程判断为True后,在进行创建
instance = new Singleton();
复制代码
之前,另一个线程也判断(instance == null),结果也为True。这样就就违背了Singleton模式的原则,保证一个类仅有一个实例。
多线程实现:
定义:
class Singleton
{
/// <summary>
/// 请注意一个关键字volatile,如果去掉这个关键字,还是有可能发生线程不是安全的。
/// </summary>
private static volatile Singleton instance = null;
/// <summary>
///创建一个静态锁
/// </summary>
private static object lockHelper = new object();
private Singleton() { }
public static Singleton getSingleton
{
get
{
if (instance == null)
{
lock (lockHelper)
{
if (instance == null)
{
instance = new Singleton();
}
}
}
return instance;
}
}
}
复制代码
说明:
这种方式采用双锁机制,安全且在多线程情况下能保持高性能。
双检锁/双重校验锁(DCL,即 double-checked locking)。
此程序对多线程是安全的,使用了一个辅助对象
lockHelper
,保证只有一个线程创建实例,如果instance为空,保证只有一个线程创建唯一的一个实例。
instance = new Singleton();
复制代码
(Double Check)
请注意一个关键字
volatile
,如果去掉这个关键字,还是有可能发生线程不是安全的。volatile 保证严格意义的多线程编译器在代码编译时对指令不进行微调。
三、优缺点分析:
优点:
在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理首页页面缓存)。
避免对资源的多重占用(比如写文件操作)。
缺点:
没有接口,既不能继承,又与单一职责原则冲突。一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。
来源:
https://www.cnblogs.com/wml-it/archive/2023/08/26/17659188.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!
上一篇:
ASP.NET Core使用JWT+标识框架(identity)实现登录验证
下一篇:
【23种设计模式】设计模式综述(开篇)
发表于 2023-8-26 18:03:36
举报
回复
使用道具
分享
返回列表
发新帖
本版积分规则
高级模式
B
Color
Image
Link
Quote
Code
Smilies
您需要登录后才可以回帖
登录
|
立即注册
快速回复
快速回复
返回顶部
返回顶部
返回列表
返回列表