C#设计模式---- 01. 单例模式(7种实现)

一. 特征

  1. 单例模式最明显特征, 在整个进程只有一个实例(注意进程和线程的区分)
  2. 针对集群系统, 在集群的每个容器, 只有一个实例, 但是, 不同的容器, 是不同的实例(未做集群可以忽略)

二. 角色类

  1. 实例类(Instance):
  2. 客户端(Client)

三. 实现

主要分为2大类: 饿汉式, 懒汉式, 每个类别中又细分为几个小类, 如下:

1. 饿汉式

a. 静态字段(属性)
//定义类
public class Instance
{
    private static Instance _instance = new Instance(); //声明私有化静态字段(也可以声明属性), 并赋值
    private Instance() //一般私有化构造函数, 避免客户端直接new实例
    {
        Console.WriteLine("构造函数Instance 执行......");
    }
    public static Instance GetInstance() // 声明静态方法, 获取实例
    {
        return _instance; // 返回声明的字段(属性)
    }
    public void Test()//声明个普通方法, 测试实例是否存在
    {
        Console.WriteLine("执行测试方法 .....");
    }
}
b. 静态方法

和静态属性区别点: 声明字段(属性)不赋初始值, 在静态构造函数里面赋值

//定义类
public class Instance
{
    private static Instance _instance;//声明私有化静态字段(也可以声明属性), <<不赋值>>
    private Instance() //一般私有化构造函数, 避免客户端直接new实例
    {
        Console.WriteLine("构造函数Instance 执行......");
    }
    static Instance()
    {
        _instance = new Instance();//对字段赋初始值
    }
    public static Instance GetInstance() // 声明静态方法, 获取实例
    {
        return _instance; // 返回声明的字段(属性)
    }
    public void Test()//声明个普通方法, 测试实例是否存在
    {
        Console.WriteLine("执行测试方法 .....");
    }
}

2. 懒汉式

a. 单if判null

不能用: 可能出现构造多次, 不能保证单例

//定义类
public class Instance
{
    private static Instance _instance;//声明私有化静态字段(也可以声明属性), 不赋值
    private Instance() //一般私有化构造函数, 避免客户端直接new实例
    {
        Console.WriteLine("构造函数Instance 执行......");
    }
    //--------------重点---------------
    public static Instance GetInstance() // 声明静态方法, 获取实例
    {
        if(_instance == null)//单if判null
        {
            _instance = new Instance();
        }
        return _instance; // 返回声明的字段(属性)
    }
    //--------------重点---------------
    public void Test()//声明个普通方法, 测试实例是否存在
    {
        Console.WriteLine("执行测试方法 .....");
    }
}
b. if判null,外层加lock

lock作用, 保证进入lock块的代码块是单线程的

不推荐: 多线程通过lock变成单线程, 无法利用多线程的优势, 意义不大

//定义类
public class Instance
{
    private static Instance _instance;//声明私有化静态字段(也可以声明属性), 不赋值
    private Instance() //一般私有化构造函数, 避免客户端直接new实例
    {
        Console.WriteLine("构造函数Instance 执行......");
    }
    //--------------重点---------------
    private static readonly object _instanceLock = new object(); //声明静态lock对象
    public static Instance GetInstance() // 声明静态方法, 获取实例
    {
        lock (_instanceLock)
        {
            if (_instance == null)//单if判null
            {
                _instance = new Instance();
            }
        }
        return _instance; // 返回声明的字段(属性)
    }
    //--------------重点---------------
    public void Test()//声明个普通方法, 测试实例是否存在
    {
        Console.WriteLine("执行测试方法 .....");
    }
}
c. 单lock外层加if判null

lock作用, 保证进入lock块的代码块是单线程的

不能用: 和单if判null一样, 不能保证单例

//定义类
public class Instance
{
    private static Instance _instance;//声明私有化静态字段(也可以声明属性), 不赋值
    private Instance() //一般私有化构造函数, 避免客户端直接new实例
    {
        Console.WriteLine("构造函数Instance 执行......");
    }
    //--------------重点---------------
    private static readonly object _instanceLock = new object();
    public static Instance GetInstance() // 声明静态方法, 获取实例
    {
        if (_instance == null)
        {
            lock (_instanceLock)
            {
            	_instance = new Instance();
            }
        }
        return _instance; // 返回声明的字段(属性)
    }
    //--------------重点---------------
    public void Test()//声明个普通方法, 测试实例是否存在
    {
        Console.WriteLine("执行测试方法 .....");
    }
}
d. lock 内外均加if判null

lock作用, 保证进入lock块的代码块是单线程的

推荐: 保证单例, 而且能充分利用多线程

//定义类
public class Instance
{
    private static Instance _instance;//声明私有化静态字段(也可以声明属性), 不赋值
    private Instance() //一般私有化构造函数, 避免客户端直接new实例
    {
        Console.WriteLine("构造函数Instance 执行......");
    }
    //--------------重点---------------
    private static readonly object _instanceLock = new object();
    public static Instance GetInstance() // 声明静态方法, 获取实例
    {
        if (_instance == null)
        {
            lock (_instanceLock)
            {
                if (_instance == null)//单if判null
                {
                    _instance = new Instance();
                }
            }
        }
        return _instance; // 返回声明的字段(属性)
    }
    //--------------重点---------------
    public void Test()//声明个普通方法, 测试实例是否存在
    {
        Console.WriteLine("执行测试方法 .....");
    }
}
e. 成员类(类中类)

推荐: 借助类的实例化机制, 在未使用的时候, 不会占用内存, 实现懒汉式, 是前面2个饿汉式实例的一个进化版本, 一样可以使用静态字段(属性),或者静态构造方法

//定义类
public class Instance
{
    private Instance() //一般私有化构造函数, 避免客户端直接new实例
    {
        Console.WriteLine("构造函数Instance 执行......");
    }
    //--------------重点---------------
    private class SubClass // 定义成员类
    {
        public static Instance _instance = new Instance();//声明私有化静态字段(也可以声明属性), 不赋值
    }
    public static Instance GetInstance() // 声明静态方法, 获取实例
    {
        return SubClass._instance;// 返回成员类字段(属性)
    }
    //--------------重点---------------
    public void Test()//声明个普通方法, 测试实例是否存在
    {
        Console.WriteLine("执行测试方法 .....");
    }
}

3. 客户端调用

客户端一个是单线程的, 一个是多线程的方法, 可以都运行以下, 加深理解

public class Client
{
    public void Run()
    {
        Console.WriteLine("单线程客户端启动......");
        Console.WriteLine("---------");
        for (int i = 0; i < 20; i++)
        {
            Instance instance = Instance.GetInstance();
            instance.Test();
        }
        Console.WriteLine("---------");
    }
    public void TaskRun()
    {
        Console.WriteLine("多线程客户端客户端启动......");
        Console.WriteLine("---------");
        for (int i = 0; i < 20; i++)
        {
            Task.Run(()=>{
                Instance instance = Instance.GetInstance();
                instance.Test();
            });
        }
        Console.WriteLine("---------");
    }
}
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值