frendguo's blog

C# 实现单例(Singleton)模式

什么是单例模式?为什么要用单例模式?

单例模式:在这个模式下,单例对象必须保证这样的实例只有一个存在。详细说明看这里》》

那为什么要用这种模式呢?

在某些时候,我们希望计算中的相同的程序只能有一个。比如在我们使用打印机的时候,我们肯定不希望有多个打印程序同时运行,造成文件打印出错。此时便需要用到单例模式。

懒汉式单例

所谓懒汉式单例,就是全局的单例实例只有在第一次使用时才会被创建。

实现方式有下面几种:

/// 单线程下的单例模式
/// 弊端:在多线程下还是会存在创建多个实例的可能
public sealed class Singleton1
{
	private Singleton1()
	{
	}

	private static Singleton1 instance = null;
	public static Singleton1 GetInstance()
	{
		if (instance == null)
		{
			instance = new Singleton1();
		}
		return instance;
	}
}
/// 多线程下的单例模式
/// 利用锁 实现了多个线程下的单例模式
/// 双重循环:只有在第一次使用的时候才会用到 lock 
/// 降低 lock 带来的性能消耗,但是还是会有不必要的性能损失
public sealed class Singleton2
{
	private Singleton2()
	{
	}

	private static Singleton2 instance = null;
	private static readonly Object obj = new object();
	public static Singleton2 GetInstance()
	{
		if (instance == null)
		{
			lock (obj)
			{
				if (instance == null)
				{
					instance = new Singleton2();
				}
			}
		}
		return instance;
	}
}
/// 使用内部 class 来实现单例模式
/// 按需创建,只会创建一次
public sealed class Singleton3
{
	private Singleton3()
	{
	}
	public static Singleton3 GetInstance()
	{
		return Nested.instance;
	}

	private class Nested
	{
		public static readonly Singleton3 instance = new Singleton3();
		static Nested()
		{
		}
	}
}

饿汉单例模式

对应懒汉单例模式,所谓饿汉单例模式,就是指全局的单例实例在类装载的时候就被创建。

/// 饿汉单例模式:在类装载的时候,单例实例就会被创建
/// 使用静态构造函数来创建
/// 在初始化 instance 的时候创建一个实例。由于
public sealed class Singleton4
{
	private static Singleton4 instance = new Singleton4();
	private Singleton4()
	{
		System.Console.WriteLine("我是Singleton 4!");
	}

	public static Singleton4 GetInstance()
	{
		return instance;
	}
}

最后总结下:

  1. 单例模式是指在应用程序的整个生命周期中单例实例只能存在一个(或没有)。
  2. 单例模式是非常重要的一个设计模式。
  3. 单例模式中单例类的构造函数必须是私有的,而且得提供一个公共的接口供别的类对象访问。
  4. 单例模式分为懒汉式单例和饿汉式单例

扩展:在继承中子类自动实现单例模式

因为前面说单例模式中单例类的构造函数必须是私有的,所以是不能继承的。看起来好像不太可能。

可仔细一想,子类的构造函数在调用的时候,会默认调用父类的构造函数,所以我们还是可以在父类构造函数那动动手脚的。

代码如下:

public abstract class Base<T> where T : new()
{
	private static T instance = new T();
	public static T Instance
	{
		get
		{
			return instance;
		}
	}
}

public sealed class Singleton5 : Base<Singleton5>
{
	public Singleton5()
	{
		System.Console.WriteLine("这里是Singleton5的构造函数!");
	}
}

同样,父类中可以用以上上面的单例模式实现那样来实现。

Happy Coding!o(* ̄▽ ̄*)o

Add comment

Loading