zoukankan      html  css  js  c++  java
  • C#设计模式之单例模式(Singleton Pattern)

    一、引言

      最近在关注设计模式的相关知识,在学习过程中在博客园查看一些设计模式的文章,所以在此记录一下学习笔记,来帮助我加深对设计模式的理解。首先我们来看一个比较的设计模式之单例模式。

    二、什么是单例模式?

      单例模式,属于创建类型的一种常用的软件设计模式。通过单例模式的方法创建的类在当前进程中只有一个实例(根据需要,也有可能一个线程中属于单例,如:仅线程上下文内使用同一个实例)(百度百科

    大家听到单例模式,第一反映就是什么是单例模式,从字面上的理解是一个类只有一个实例,所以单例模式就是保证一个类有且只有一个实例,并提供一个访问它的全局访问点,简单来说单例模式的作用就是保证在程序生命周期中,任何时刻单例类都只存在一个实例。

    三、为什么有单例模式?

      为什么要有单例模式?它在什么情况下使用的?从单例模式的定义中我们可以看出——单例模式的使用自然是当我们的系统中某个对象只需要一个实例的情况,例如:操作系统中只能有一个任务管理器,操作文件时,同一时间内只允许一个实例对其操作等,既然现实生活中有这样的应用场景,自然在软件设计领域必须有这样的解决方案了(因为软件设计也是现实生活中的抽象),所以也就有了单例模式了。

    四、单例模式的要点

    • 单例类只能有一个实例
    • 必须自行创建这个类实例
    • 必须自行向整个系统提供这个实例

    五、写法:线程不安全(一)

     public sealed class Singleton
        {
            private static Singleton _instance = null;
            private Singleton() { }
            public static Singleton CreateSingleton()
            {
                if (_instance == null)
                {
                    Console.WriteLine("Singleton实例化一次!");
                    _instance = new Singleton();
                }
                return _instance;
            }
            public void Show()
            {
                Console.WriteLine($"这是{this.GetType().Name}.Show方法!");
            }          
        }

     分析:

    • sealed修饰符表示密封此类,该类不能再被继承。
    • 静态变量加载在内存中,它的生命周期跟整个应用程序的生命周期一样,直至应用程序退出结束。这里定义一个私有的静态全局变量_instance来保存该类的唯一实例。
    • 私有构造方法防止别的地方new()一个该实例对象。
    • getInstance()提供一个全局访问点,并通过if判断对象是否为null,如果为null自行创建Singleton对象实例,再返回类实例。

     调用:

    class Program
        {
            static void Main(string[] args)
            {
                for (int i = 0; i < 5; i++)
                {
                    Task.Run(() =>
                    {
                        Singleton singleton = Singleton.CreateSingleton();
                        singleton.Show();
                    });
                }
                Console.Read();
            }
        }

    上面的代码中,未考虑多线程,所以在调用单例类时,Singleton被实例化多次,结果如下:

    六、写法:线程安全(二)

     public sealed class Singleton
        {
            private static Singleton singleton = null;
    
            private static object _lock = new object();
    
            private Singleton()
            {
    
            }
            public static Singleton CreateSingleton()
            {
                if (singleton == null)
                {
                    lock (_lock)
                    {
                        if (singleton == null)
                        {
                            singleton = new Singleton();
                            Console.WriteLine("Singleton实例化一次!");
                        }
                    }
                }
                return singleton;
            }
    
            public void Show()
            {
                Console.WriteLine($"这是{this.GetType().Name}.Show方法!");
            }
        }

     结果:

    七、写法:静态构造函数(三)

    public class SingletonSecond
        {
            private static SingletonSecond singletonSecond = null;
            private SingletonSecond()
            {
    
            }
            //初始化一次
            static SingletonSecond()
            {
                singletonSecond = new SingletonSecond();
                Console.WriteLine("SingletonSecond被创建了!");
            }
            public static SingletonSecond CreateSingletonSecond()
            {
                return singletonSecond;
            }
            public void Show()
            {
                Console.WriteLine($"这是{this.GetType().Name}.Show方法!");
            }
    
        }

     分析:

    因为静态构造函数在创建第一个实例或引用任何静态成员之前(且只调用一次),将自动调用静态构造函数来初始化类。  参考:C#静态构造函数   静态构造函数

    结果:

    八、写法:静态变量(四)

     public class SingletonThird
        {
            private static SingletonThird singletonThird =  new SingletonThird();
            private SingletonThird()
            {
    
            }
            public static SingletonThird CreateSingletonSecond()
            {           
                return singletonThird;
            }
        }

     源码下载

  • 相关阅读:
    从浏览器输入URL到页面渲染的过程
    安全分析的几个好的工具网站的使用
    从一次渗透谈到linux如何反弹shell
    python 进行抓包嗅探
    MYSQL的索引和常见函数
    一篇博客搞定redis基础
    新型横向移动工具原理分析、代码分析、优缺点以及检测方案
    Java反序列化漏洞的挖掘、攻击与防御
    关于Memcached反射型DRDoS攻击分析
    spark未授权RCE漏洞
  • 原文地址:https://www.cnblogs.com/liujie2272/p/13268870.html
Copyright © 2011-2022 走看看