单例模式

        近期做项目时初期设计某个模块时,同事说应该用简单工厂模式,我只听说过简单工厂模式但不太了解。我把写的demo给他看,同事一看说这就是简单工厂呀,瞬间感觉弱爆了,还是要加强理论知识呀,工作两年了,对设计模式只是听听名称,一直没去专研。下了个大话设计模式电子书,大概过了一遍,准备把现在工作接触到的先研究做个记录。

        先从软柿子捏了,单例模式是听得最多的也是我认为最简单的,不过学习了之后还是有颇多收获。
        学习的过程也找了几种实现方式:
        方法一:

public class Singleton
{
    private static Singleton instance;
    //私有构造函数,不让外界构造实例
    private Singleton() { }
    //开放实例的全局访问点
    public static Singleton GetInstance()
    {
        if (instance == null)
        {
            instance = new Singleton();
        }
        return instance;
    }
}

        这种方式的缺点是多线程时不能保证单一实例;
        由此引入第二种方法,保证在多线程下单一实例:

/// <summary>
/// 懒汉式单例类-双重锁定
/// </summary>
public class Singleton
{
    private static Singleton instance;
    private static readonly object syncRoot = new object();
    //私有构造函数,不让外界构造实例
    private Singleton() { }
    //开放实例的全局访问点
    public static Singleton GetInstance()
    {
        //只有当实例未创建时才锁
        if (instance == null)
        {
            lock (syncRoot)
            {
                if (instance == null)
                {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

        不过C#还有简单的实现,静态初始化:

/// <summary>
/// 饿汉式单例类-静态初始化
/// </summary>
public sealed class Singleton
{
    private static readonly Singleton instance=new Singleton();
    //私有构造函数,不让外界构造实例
    private Singleton(){}
    //开放实例的全局访问点
    public static Singleton GetInstance()
    {
        return instance;
    }
}

        这种静态初始化的方式是在自己被加载时就将自己实例化,所以被形象的称之为饿汉式单例类,而方法二要在第一次被引用时才会被实例化,所以称为懒汉式单例类。
        后来查看相关的文章发现还有好多实现方法,特别有一种方法是对方法三的优化:

/// <summary>
/// 饿汉式单例类-静态初始化--延时初始化
/// </summary>
public sealed class Singleton
{
    // 因为下面声明了静态构造函数,所以在第一次访问该类之前,new Singleton()语句不会执行
    private static readonly Singleton instance = new Singleton();
    //私有构造函数,不让外界构造实例
    private Singleton() { }
    // 声明静态构造函数就是为了删除IL里的BeforeFieldInit标记
    // 以去除静态变量在使用之前被初始化
    static Singleton() { }
    //开放实例的全局访问点
    public static Singleton GetInstance()
    {
        return instance;
    }
}

        方法三需要注意的是,C#其实并不保证实例创建的时机,因为C#规范只是在IL里标记该静态字段是BeforeFieldInit,也就是说静态字段可能在第一次被使用的时候创建,也可能你没使用了,它也帮你创建了,也就是周期更早,我们不能确定到底是什么创建的实例。而方法四保证了是个延迟初始化的单例(通过加静态构造函数),要注意的是该静态构造函数里没有东西,所以实际写时要加上注释防止被后期维护的人删掉。

参考:

1.大话设计模式,程杰;

2.博客园的汤姆大叔

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值