最简单的设计模式之单例模式

单例模式是现在最常用的软件设计模式,也是最简单设计模式,通过单例模式可以保证系统中,这个类只有一个实例

假如在下面这种情况下,我们有一个数据库连接类,在平常的时候,我们实例化这个类然后写入连接,第一次我链接了SQLServer数据库,第二次我链接了MySql数据库,但是我同时想用这两个数据库,发现不太合适,就需要一个方法方式来解决问题,这是最适合用单例模式了

虽然我举的栗子可能不太合适,但是大概就是这么一个意思,保证只有一个实例,避免多个实例不知道使用哪个或者多个实例导致报错

使用

单例模式要求类能够返回一个对象的引用和一个获得该实例的方法,静态的方法

实现主要是有两个步骤:

①:经该类的构造函数定义为私有的(private)

②:在这个类里提供一个静态方法

在这里要区别的是单例模式有两种:恶汉模式和懒汉模式

恶汉模式是在项目运行起来就实例化了这个类

懒汉模式是在需要这个类的时候才实例化这个类

先不多说了,上代码:

这个是恶汉模式:

/// <summary>
/// 单例模式的实现 /// </summary> public class SingletonEh { // 定义一个静态变量来保存类的实例 private static SingletonEh uniqueInstance=new SingletonEh(); private SingletonEh() { } /// <summary> /// 定义公有方法提供一个全局访问点,同时你也可以定义公有属性来提供全局访问点 /// </summary> /// <returns></returns> public static SingletonEh GetInstance() { return uniqueInstance; } } 

这个是不安全的懒汉模式:

/// <summary>
/// 单例模式线程不安全的实现(懒汉模式) /// </summary> public class SingletonThread { // 定义一个静态变量来保存类的实例 private static SingletonThread uniqueInstance; // 定义一个标识确保线程同步 private static readonly object locker = new object(); // 定义私有构造函数,使外界不能创建该类实例 private SingletonThread() { } /// <summary> /// 定义公有方法提供一个全局访问点,同时你也可以定义公有属性来提供全局访问点 /// </summary> /// <returns></returns> public static SingletonThread GetInstance() { // 如果类的实例不存在则创建,否则直接返回 if (uniqueInstance == null) { uniqueInstance = new SingletonThread(); } return uniqueInstance; } } 

大家可能注意到了我说的是不安全的懒汉模式,别急,这就来解释,在懒汉模式中,如果单线程的话没问题,如果是多线程呢,加入同时两个线程需要使用这个类,通过代码可以看到,都通过判断,都实例化了这个类,那就没有单例模式的意义了,既然有问题就有解决办法,下面这个是线程安全的单例模式,加锁的单例模式

/// <summary>
/// 单例模式线程安全的实现(懒汉模式) /// </summary> public class SingletonThread { // 定义一个静态变量来保存类的实例 private static SingletonThread uniqueInstance; // 定义一个标识确保线程同步 private static readonly object locker = new object(); // 定义私有构造函数,使外界不能创建该类实例 private SingletonThread() { } /// <summary> /// 定义公有方法提供一个全局访问点,同时你也可以定义公有属性来提供全局访问点 /// </summary> /// <returns></returns> public static SingletonThread GetInstance() { // 当第一个线程运行到这里时,此时会对locker对象 "加锁", // 当第二个线程运行该方法时,首先检测到locker对象为"加锁"状态,该线程就会挂起等待第一个线程解锁 // lock语句运行完之后(即线程运行完之后)会对该对象"解锁" lock (locker) { // 如果类的实例不存在则创建,否则直接返回 if (uniqueInstance == null) { uniqueInstance = new SingletonThread(); } } return uniqueInstance; } } 

这很安全了,但是,每次使用我都得等上一个任务完成解锁后才可以继续,这就造成了可能排老长的队,也不太合适,那么,咱们继续优化一下

/// <summary>
/// 优化后的单例模式线程安全的实现(懒汉模式) /// </summary> public class SingletonThreadOptimize { // 定义一个静态变量来保存类的实例 private static SingletonThreadOptimize uniqueInstance; // 定义一个标识确保线程同步 private static readonly object locker = new object(); // 定义私有构造函数,使外界不能创建该类实例 private SingletonThreadOptimize() { } /// <summary> /// 定义公有方法提供一个全局访问点,同时你也可以定义公有属性来提供全局访问点 /// </summary> /// <returns></returns> public static SingletonThreadOptimize GetInstance() { // 当第一个线程运行到这里时,此时会对locker对象 "加锁", // 当第二个线程运行该方法时,首先检测到locker对象为"加锁"状态,该线程就会挂起等待第一个线程解锁 // lock语句运行完之后(即线程运行完之后)会对该对象"解锁" // 双重锁定只需要一句判断就可以了 if (uniqueInstance == null) { lock (locker) { // 如果类的实例不存在则创建,否则直接返回 if (uniqueInstance == null) { uniqueInstance = new SingletonThreadOptimize(); } } } return uniqueInstance; } } 

优点

系统内存中该类只存在一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能。

缺点

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

猜你喜欢

转载自www.cnblogs.com/linjierd/p/11130313.html
今日推荐