单例模式经典案例
1、应用场景
全局类频繁的创建和销毁,常用于不同窗体传参问题(优于静态类和构造函数传参)
核心:一个类仅有一个实例 (最简单的设计模式)
- 唯一编号问题(道路标识码之类或计数)
- 不同窗体传参
2、实现方式
1)懒汉式 (调用了方法才去构造 懒汉)
c# 懒汉式 (多线程安全)
public class Singleton {
private Singleton()
{
}
private static volatile Singleton _Singleton = null;
private static object Singleton_Lock = new object();
public static Singleton CreateInstance()
{
if (_Singleton == null)
{
lock (Singleton_Lock)
{
if (_Singleton == null)
_Singleton = new Singleton();
}
}
return _Singleton;
}
}
java 懒汉式 (多线程安全)
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
2)饿汉式 (只要使用类就会被构造,多线程安全)
** c# java 代码同:**
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
3)双检锁/双重校验锁 (多线程安全, 懒汉式 )
c# 双检锁/双重校验锁
/// <summary>
/// 单例模式类
/// </summary>
public class ApplicationUtil
{
private ApplicationUtil ()
{}
/// <summary>
/// 事件的实例
/// </summary>
private static ApplicationUtil instance = null;
/// <summary>
/// 线程锁
/// </summary>
private static readonly object _lock = new object();
/// <summary>
/// 获取对象实例,如果不存在就实例化,否则就直接返回实例
/// </summary>
/// <param name="mapControl"></param>
/// <returns></returns>
public static ApplicationEventUtil GetInstance()
{
//第一次校验
if (instance == null)
{
lock (_lock)
{
//第二次校验
if (instance == null)
{
instance = new ApplicationUtil();
}
}
}
return instance;
}
/// <summary>
/// 事件存储中心
/// </summary>
Dictionary<string, object> Datas = new Dictionary<string, object>();
/// <summary>
/// 设置关键字对应的数据,并激发关联到关键字上的事件
/// </summary>
/// <param name="cKey">事件关键字</param>
/// <param name="cData">关键字关联的数据</param>
public void SetData(string cKey, object cData)
{
//存在关键字的话,设置关键字
if (Datas.ContainsKey(cKey))
{
try
{
Datas[cKey] = cData;
}
catch
{
}
return;
}
//不存在的新建关键字
try
{
Datas.Add(cKey, cData);
}
catch { }
}
/// <summary>
/// 获取关键字关联的数据
/// </summary>
/// <param name="cKey">关键字</param>
/// <returns>返回关键字数据,无此关键字返回null</returns>
public object GetData(string cKey)
{
try
{
if (Datas.ContainsKey(cKey))
{
return Datas[cKey];
}
}
catch
{
return null;
}
}
/// <summary>
/// 移除相应的键
/// </summary>
/// <param name="cKey"></param>
public void RemoveData(string cKey)
{
if (Datas.Keys.Contains(cKey))
{
Datas.Remove(cKey);
}
}
}
}
java 双检锁/双重校验锁
public class Singleton {
private volatile static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
//第一次校验
if (singleton == null) {
synchronized (Singleton.class) {
//第二次校验
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
3、结论:
1)第三种模式为经典模式,使用频率最高
2)双检锁/双重校验锁 (推荐使用,线程安全,双锁机制,性能高)
在java中使用双重校验锁,注意:
1、volatile 关键词不可缺少
2、以上同使用映射的方式可破坏单例模式,以上方式并非绝对安全的单例模式,通常开发中,无需考虑映射破坏单例模式的问题,遇到此类问题,您可以使用枚举的方式创建单例模式解决此问题(略)
4、声明
1)文章来源于项目实践,如存在问题或疑问,请留言,感谢您的阅读,谢谢!
2)转载请标注来源,感谢您的阅读