设计模式(4)---单例模式
学习设计模式,必然会谈到单例模式,因为它是一种很常用的软件设计模式,本节开始学习单例模式,首先解释单例模式的定义、分类,接着实例介绍饿汉式单例模式类、懒汉式单例模式类、在多线程中的应用及它们的区别,最后列举一个单例模式的实例,以供参考。
定义:
单例模式:保证一个类仅有一个实例,并提供一个全局访问点。
相关解释:在应用单例模式时,单例对象的类必须保证只有一个实例存在。许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息。这种方式简化了在复杂环境下的配置管理。
单例模式一般分为两大类:
1、饿汉式单例:静态初始化的方式是在自己被加载时就将自己实例化;
2、懒汉式单例:在第一次被引用时,才会将自己实例化。
实现:
实现单例模式的思路是:一个类能返回对象一个引用(永远是同一个)和一个获得该实例的方法(必须是静态方法,通常使用getInstance这个名称);当我们调用这个方法时,如果类持有的引用不为空就返回这个引用,如果类保持的引用为空就创建该类的实例并将实例的引用赋予该类保持的引用;同时我们还将该类的构造函数定义为私有方法,这样其他处的代码就无法通过调用该类的构造函数来实例化该类的对象,只有通过该类提供的静态方法来得到该类的唯一实例。
饿汉式单例模式类:
//饿汉式 class Singleton { private static Singleton instance = new Singleton(); private Singleton() { } public static Singleton GetInstance() { return instance; } }
懒汉式单例模式类:
//懒汉式 class Singleton { private static Singleton instance; private Singleton() { } public static Singleton GetInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
在多线程中应用:
在多线程的应用场合下必须小心使用。如果当唯一实例尚未创建时,有两个线程同时调用创建方法,那么它们同时没有检测到唯一实例的存在,从而同时各自创建了一个实例,这样就有两个实例被构造出来,从而违反了单例模式中实例唯一的原则。 解决这个问题的办法是为指示类是否已经实例化的变量提供一个互斥锁(虽然这样会降低效率)。
代码实例:
class Singleton { private static Singleton instance; private static readonly object obj = new object(); private Singleton() { } public static Singleton GetInstance() { if (instance == null) { lock (obj) { if (instance == null) { instance = new Singleton(); } } } return instance; } }
饿汉式和懒汉式区别:
饿汉式,即静态初始化式,它是在类第一次加载就实例化的对象,所以需要提前占用系统资源。
懒汉式:虽然不会有饿汉式的问题,但是它会面临着多线程访问的安全性问题,需要做双重锁定的处理才能保证系统安全,同样会降低效率。
具体如何使用,就需要取决育实际,没有谁好谁劣。
实例:
列举一个完整的例子,谨供参考。功能:新建一个Form1窗体,Form1窗体中有一个button控件,弹出一个FormToolbox窗体。要求:每次只能弹出一个FormToolbox窗体,只有在关闭FormToolbox窗体时才允许系统重新弹出新的FormToolbox窗体。
贴代码:
//Form1窗体: private void Form1_Load(object sender, EventArgs e) { this.IsMdiContainer = true; } private void button1_Click(object sender, EventArgs e) { FormToolbox.GetInstance().Show(); } //FormToolbox窗体: public partial class FormToolbox : Form { private static FormToolbox ftb = null; private FormToolbox() { InitializeComponent(); } public static FormToolbox GetInstance() { if (ftb == null || ftb.IsDisposed) { ftb = new FormToolbox(); ftb.MdiParent = Form1.ActiveForm; } return ftb; } }
到此,单例模式讲解完毕。
补充:
正如一位园友fsllsf所说,还有一种方式:
C#与公共语言运行库提供了一种“静态初始化”方法,这种方法不需要开发人员显式地编写线程安全代码,即可解决多线程环境下它是不安全的问题。
public sealed class Singleton { private static readonly Singleton instance = new Singleton(); private Singleton() { } public static Singleton GetInstance() { return instance; } }