单例模式之简约美

简介:         生活中的单例         中国(China),位于东亚,是一个以华夏文明为主体、中华文化为基础,以汉族为主要民族的统一多民族国家,通用汉语。

        生活中的单例

        中国(China),位于东亚,是一个以华夏文明为主体、中华文化为基础,以汉族为主要民族的统一多民族国家,通用汉语。中国疆域内的各个民族统称为中华民族,龙是中华民族的象征。古老的中国凭借自身的发展依旧美丽的屹立于东方民族之林,闪耀着她动人的光彩,世界上只有一个中国,任何部分都是祖国不可分割的一部分,今天我们的设计模式就从伟大的祖国开始说起---单例模式。


       详解单例模式
       单例模式是什么?跟我们的祖国有着怎样的关系呢?首先我们来看一下单例,从“单例”字面意思上理解为—一个类只有一个实例,所以单例模式也就是保证一个类只有一个实例的一种实现方法。官方定义:确保一个类只有一个实例,并提供一个全局访问点。在学习的过程中,我们需要把握三个主要的关键点,一、某个类只能有一个实例;二、它必须自行创建这个实例;三、它必须自行向整个系统提供这个实例。来看一下单例模式的结构图:

       
        

       实现方法

        一个类能返回对象一个引用(永远是同一个)和一个获得该实例的方法(必须是静态方法,通常使用getInstance这个名称);当我们调用这个方法时,如果类持有的引用不为空就返回这个引用,如果类保持的引用为空就创建该类的实例并将实例的引用赋予该类保持的引用;同时我们还将该类的构造函数定义为私有方法,这样其他处的代码就无法通过调用该类的构造函数来实例化该类的对象,只有通过该类提供的静态方法来得到该类的唯一实例。


      代码实现

      第一版(基本代码)

     

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Text;  
  
namespace 单例模式基本模型  
{  
    class Program  
    {  
        //客户端  
        static void Main(string[] args)  
        {  
            Singleton Instance1 = Singleton.GetInstance();  
            Singleton Instance2 = Singleton.GetInstance();  
  
            if (Instance1 == Instance2)  
            {  
                Console.WriteLine("两个实例是一模一样的实例。");  
            }  
  
        }  
    }  
    class Singleton  
    {  
        private static Singleton instance;  
  
        //构造方法采用private,外界便无法用new创建该类的实例  
        private Singleton()  
        { }  
  
        //该方法提供一个获得该类实例的全局访问点,是唯一的  
        public static Singleton GetInstance()  
        {  
            //如果实例不存在,则返回一个新实例,否则返回原实例。  
            if (instance == null)  
            {  
                instance = new Singleton();  
            }  
            return instance;  
        }  
    }  
}  

        但是上述代码存在一些缺点,线程不安全,多线程情况下,多个线程同时访问Singleton,调用GetInstance()方法,同时判断instance==null,得到真值,导致创建多个实例,这不符合单例模式的基本原则。那我们要怎么办捏,为了解决以上缺点,我们来看改进的代码(一下版本的)


        第二版(多线程时的单例)

        

class Singleton  
    {  
        private static Singleton instance=null;  
        //创建一个静态只读的进程辅助对象  
        private static readonly object ProgressLock = new object();  
  
        //构造方法采用private,外界便无法用new创建该类的实例  
        private Singleton()  
        { }  
  
        //该方法提供一个获得该类实例的全局访问点,是唯一的  
        public static Singleton GetInstance()  
        {  
            lock (ProgressLock)  
            {  
                  
                if (instance == null)  
                {  
                    instance = new Singleton();  
                }  
            }  
             
            return instance;  
        }  
    }  

        每次调用GetInstance()方法都需要lock,这种做法是会影响性能的,所以我们需要对这个类进行改良。


         第三版(双重锁定)

          

class Singleton  
    {  
        private static Singleton instance=null;  
        //创建一个静态只读的进程辅助对象  
        private static readonly object ProgressLock = new object();  
  
        //构造方法采用private,外界便无法用new创建该类的实例  
        private Singleton()  
        { }  
  
        //该方法提供一个获得该类实例的全局访问点,是唯一的  
        public static Singleton GetInstance()  
        {  
            if (instance == null)  
            {  
                lock (ProgressLock)  
                {  
  
                    if (instance == null)  
                    {  
                        instance = new Singleton();  
                    }  
                }  
            }  
                   
            return instance;  
        }  
    }  
        上述构造方式只有在实例未被创建的时候才加锁,避免了每次调用GetInstance()方法都加锁损失性能的问题。但是相对于后面的做法,她仍然有着美中不足的地方。

         第四版(静态初始化)

          

//sealed关键字防止派生  
    public sealed class Singleton  
    {  
        //在第一次引用类的成员时创建实例,公共语言运行库负责处理变量的初始化  
        private static readonly Singleton instance=new Singleton();  
         
        //构造方法采用private,外界便无法用new创建该类的实例  
        private Singleton()  
        { }  
  
        public static Singleton GetInstance()  
        {  
            return instance;  
        }  
    }  

       这种方式是在自己被加载时就将自己实例化,称为饿汉式。由于有.NetFramework 进行初始化,所以我们对实例化机制的控制权较少,没办法和其他实现一样实现延迟初始化。在上面三种形式中,您能够在实例化之前使用非默认的构造函数或执行其他任务。


          第五版(完全延迟加载实例化)

       

public sealed class Singleton   
 {  
        private Singleton()  
        {  
        }  
        public static Singleton GetInstance()  
        {  
            return Nested.instance;  
        }  
        class Nested  
        {  
            static Nested()  
            {  
            }  
            internal static readonly Singleton instance = new Singleton();  
        }  
    }  
        
           
       写在后面的话
       前三版编程方法,因为会面临多线程访问安全的问题,需要做双重锁定这样的处理才可以保证安全,但能够在实例化之前使用非默认的构造函数或执行其他任务,第四版(静态初始化方式)是类一加载就实例化的对象,占用系统资源,所以到底实用哪一种方式,视具体情况而定.

目录
相关文章
|
4月前
|
设计模式 API 图形学
Unity精华☀️ 「设计模式」的终极详解!
Unity精华☀️ 「设计模式」的终极详解!
|
4月前
|
设计模式 安全 图形学
Unity精华☀️ 面试官眼中的「设计模式」
Unity精华☀️ 面试官眼中的「设计模式」
|
7月前
|
存储 安全 编译器
C++类和对象万字详解(典藏版)
C++类和对象万字详解(典藏版)
|
存储 Java C++
C嘎嘎~~[类和对象 精华篇]
C嘎嘎~~[类和对象 精华篇]
|
小程序 Oracle Java
设计:小即是美
设计:小即是美
设计:小即是美
|
设计模式 存储 SQL
万字速通单例模式
谈起单例模式,想必大家都不陌生,不仅在各种大厂的面试中频频出现,在实际的开发中,也应用广泛,如何设计一个优雅的单例模式,成为了重头戏。
127 0
万字速通单例模式
|
存储 设计模式 Java
漫画:什么是 “原型模式” ?
在Java语言中,Object类实现了Cloneable接口,一个对象可以通过调用Clone()方法生成对象,这就是原型模式的典型应用。 但需要注意的是,clone()方法并不是Cloneable接口里的,而是Object类里的,Cloneable是一个标识接口,标识这个类的对象是可被拷贝的,如果没有实现Cloneable接口,却调用了clone()方法,就会报错。
220 0
漫画:什么是 “原型模式” ?
|
安全 Java 编译器
漫画:什么是单例模式?(整合版)
为什么这样写呢?我们来解释几个关键点: 1.要想让一个类只能构建一个对象,自然不能让它随便去做new操作,因此Signleton的构造方法是私有的。 2.instance是Singleton类的静态成员,也是我们的单例对象。它的初始值可以写成Null,也可以写成new Singleton()。至于其中的区别后来会做解释。 3.getInstance是获取单例对象的方法。
174 0
漫画:什么是单例模式?(整合版)
|
设计模式 前端开发
前端仔学学设计模式--单例模式
设计模式知识提取将分为N篇文章,本篇文章是个开篇文,后期会进行其他相关的同步(会就分享,不会就折腾),旨在提升技能,更好地享受敲键盘的快感~
前端仔学学设计模式--单例模式
|
设计模式 安全 Java
单例模式-温故而知新
单例模式,应该是使用频率比较高的一种设计模式了。
130 0