单例模式之简约美

简介:         生活中的单例         中国(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();  
        }  
    }  
        
           
       写在后面的话
       前三版编程方法,因为会面临多线程访问安全的问题,需要做双重锁定这样的处理才可以保证安全,但能够在实例化之前使用非默认的构造函数或执行其他任务,第四版(静态初始化方式)是类一加载就实例化的对象,占用系统资源,所以到底实用哪一种方式,视具体情况而定.

目录
相关文章
|
2月前
|
存储 安全 编译器
C++类和对象万字详解(典藏版)
C++类和对象万字详解(典藏版)
|
6月前
|
设计模式 存储 数据库
设计模式六大原则 节选自《闻缺陷则喜》(此书可免费下载)
设计模式六大原则 节选自《闻缺陷则喜》(此书可免费下载)
|
7月前
|
设计模式 算法
趣解设计模式之《会飞的橡皮鸭》
趣解设计模式之《会飞的橡皮鸭》
56 0
|
设计模式 缓存 JavaScript
设计模式(二)—— 创建型模式|牛气冲天新年征文
设计模式(二)—— 创建型模式|牛气冲天新年征文
68 0
|
设计模式 存储 SQL
万字速通单例模式
谈起单例模式,想必大家都不陌生,不仅在各种大厂的面试中频频出现,在实际的开发中,也应用广泛,如何设计一个优雅的单例模式,成为了重头戏。
106 0
万字速通单例模式
|
设计模式 算法 前端开发
漫画:什么是 “设计模式” ?
1.创建型模式 这一类设计模式的目的是用于创建对象。 2.结构型模式 这一类设计模式的目的是优化不同类、对象、接口之间的结构关系。 3.行为型模式 这一类设计模式的目的是更好地实现类与类之间的交互以及算法的执行。
131 0
|
安全 Java 编译器
漫画:什么是单例模式?(整合版)
为什么这样写呢?我们来解释几个关键点: 1.要想让一个类只能构建一个对象,自然不能让它随便去做new操作,因此Signleton的构造方法是私有的。 2.instance是Singleton类的静态成员,也是我们的单例对象。它的初始值可以写成Null,也可以写成new Singleton()。至于其中的区别后来会做解释。 3.getInstance是获取单例对象的方法。
149 0
漫画:什么是单例模式?(整合版)
初见“子母类”-内部类 | 带你学《Java面向对象编程》之八十二
本节向读者介绍了内部类的概念,并结合案例通过一系列的思考引发读者对内部类带来的优势的思考,以能深入了解内部类。
设计模式之死磕抽象工厂模式(原创)
之前提到过工厂模式仔细区分的话分为三种,分别是简单工厂模式、工厂方法模式以及抽象工厂模式。在上面已经介绍完了工厂模式和工厂方法模式。本篇文章主要学习的是工厂模式的第三种,抽象工厂模式。
1209 0
|
设计模式 开发者 数据库
设计模式之死磕工厂方法模式(原创)
在 设计模式之工厂模式 中,我们提到过工厂模式仔细区分的话分为三种,分别是简单工厂模式、工厂方法模式以及抽象工厂模式。在上面已经介绍完毕了工厂模式(也就是简单工厂模式)。
911 0