设计模式创建型模式之单例模式

Posted yheng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式创建型模式之单例模式相关的知识,希望对你有一定的参考价值。

单例模式

单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的一个类只有一个实例。即一个类只有一个对象实例。

简单的理解:保证这一个类仅有一个实例,并提供一个访问它的全局访问点。

通常我们可以让一个全局变量使得一个对象被访问,但它不能防止你实例化多个对象。一个最好的办法就是,让类自身负责保存它的唯一实例。这个类可以保证没有其他实例可以被创建,并且它可以提供一个访问该实例的方法。

实现思路

  1. 将该类的构造方法定义为私有方法,这样其他处的代码就无法通过调用该类的构造方法来实例化该类的对象,只有通过该类提供的静态方法来得到该类的唯一实例【Lazy Singleton(懒汉式单例类)】
  2. 在该类内提供一个静态方法,当我们调用这个方法时,如果类持有的引用不为空就返回这个引用,如果类保持的引用为空就创建该类的实例并将实例的引用赋予该类保持的引用【Eager Singleton(饿汉式单例类)】

单例模式特点

  1. 单例类只能有一个实例
  2. 单例类必须自己创建自己的唯一实例
  3. 单例类必须给所有其他对象提供这一实例

单例模式的几种实现方式

1.Lazy Singleton(懒汉式单例类)

其类的唯一实例在真正调用时才被创建,而不是类加载时就被创建。所以Lazy Singleton不是线程安全的。

这种方式是最基本的实现方式,这种实现最大的问题就是不支持多线程。所以严格意义上它并不算单例模式。
这种方式 lazy loading 很明显,不要求线程安全,在多线程不能正常工作。

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 
 7 namespace _21单例模式01
 8 {
 9     class Program
10     {
11         static void Main(string[] args)
12         {
13             Singleton s1 = Singleton.GetInstance();
14             Singleton s2 = Singleton.GetInstance();
15             if (s1 == s2)
16             {
17                 Console.WriteLine("两个对象是相同的实例。");
18             }
19             Console.Read();
20         }
21     }
22     class Singleton
23     {
24         private static Singleton instance;
25         private Singleton()
26         {
27 
28         }
29         public static Singleton GetInstance()
30         {
31             if (instance == null)
32             {
33                 instance = new Singleton();
34             }
35             return instance;
36         }
37     }
38 }

 

2.懒汉式(双锁保证线程安全)

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 
 7 namespace _21单例模式_多线程单例_
 8 {
 9     class Program
10     {
11         static void Main(string[] args)
12         {
13         }
14     }
15 
16     class Singleton
17     {
18         private static Singleton instance;
19         private static readonly object syncRoot = new object();
20         private Singleton()
21         {
22 
23         }
24 
25         //双重锁定
26         //为什么会有两个 instance==null
27         /*
28         两个线程同时访问第一阶段:instance,大家得到的都是null
29         然后由lock机制,两个线程只有一个进入,而另外一个线程需要等待
30         当第一个线程完成后,第二个线程则进入,如果不加判断,第二个线程也会在 new 一次
31         */
32         public static Singleton GetInstance()
33         {
34             if (instance == null)
35             {
36                 lock (syncRoot)
37                 {
38                     if (instance == null)
39                     {
40                         instance = new Singleton();
41                     }
42                 }
43             }
44             return instance;
45         }
46     }
47 }

 

3.Eager Singleton(饿汉式单例类)

其静态成员在类加载时就被初始化,此时类的私有构造函数被调用,单例类的唯一实例就被创建

 1 class EagerSingleton
 2 {
 3     private static readonly EagerSingleton instance = new EagerSingleton();
 4 
 5     private EagerSingleton() { }
 6 
 7     public static EagerSingleton GetInstance()
 8     {
 9         return instance;
10     }
11 }

 

两者之间的区别

饿汉式:即静态初始化的方式,它是类一加载就实例化的对象,所以要提前占用系统资源。

懒汉式:面临这多线程访问的安全性问题。需要做双重锁定这样的处理才可以保证安全。

优点

1、在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例

2、避免对资源的多重占用

缺点:

没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。

当想实例化一个单例类的时候,必须要记住使用相应的获取对象的方法,而不是使用new,可能会给其他开发人员造成困扰,特别是看不到源码的时候。

单例模式与静态类区别

单例可以继承类,实现接口,而静态类不能
单例可以被延迟初始化,静态类一般在第一次加载是初始化
静态类占资源,不断初始化和释放

以上是关于设计模式创建型模式之单例模式的主要内容,如果未能解决你的问题,请参考以下文章

Java设计模式——创建型模式之单例模式

JAVA SCRIPT设计模式--创建型设计模式之单例模式

创建型模式之单例模式

创建型模式之单例模式

3创建型模式之单例模式

设计模式之单例模式(创建型)