Loading

设计模式——单例模式的实现[备忘录]

单例模式(Singleton):保证一个类仅有一个实例,并提供一个访问它的全局访问点。

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

结构图:

先创建一个简单的实例说明一下单例模式:

Singleton类:

/*
 * 单例模式的实现
 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Singleton
{
    public class Singleton
     {
        private static Singleton instance;

        //定义其构造方法为private,防止外界利用new创建此类实例的可能。
        private Singleton() { }          
       

        //通过此方法获得本类实例的唯一全局访问点。
        public static Singleton Instance()
        {
            if (instance==null )//若实例不存在,则new一个新实例,否则返回已有的实例;
            {
                instance = new Singleton();
                
            }
            return instance;
        }
        
    }
    
}

客户端调用:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Singleton
{
    class Program
    {
        

        static void Main(string[] args)
        {

            Singleton s1 = Singleton.Instance();
            Singleton s2 = Singleton.Instance();
            if (s1==s2)
            {
                Console.WriteLine("两个对象是相同的实例。");
                
            }

            Console.ReadLine();
            
        }

       
    }
}

单例模式的初衷是为了保证一个类仅有一个实例。而在多线程就不能保证一个类在多个线程访问下,拥有一个实例。那么我们在多线程的环境下,怎么实现单例模式呢?

Singleton类:

/*
 * 单例模式的实现
 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Singleton
{
    /// <summary>
    /// 安全线程的实现
    /// </summary>
    public sealed class Singleton
    {
        private static Singleton instance = null;

        //程序运行时创建一个静态只读的进程辅助对象
        private static readonly object padlock = new object();
        private Singleton() { }

        public static Singleton Instance()
        {
            lock (padlock)  //在同一个时刻加了锁的那部分程序只有一个进程可以进入。
            {
                if (instance == null)
                {
                    instance = new Singleton();

                }
                return instance;

            }

        }

    }
}


创建padlock对象的目的:在进程加锁时,instance实例有没有创建并不知道,无法加锁。

但是每次调用Instance时,总需要lock,会影响性能,接下来我们做一下改良。

双重锁定:

/*
 * 单例模式的实现
 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Singleton
{
    /// <summary>
    /// 安全线程的实现
    /// </summary>
    public sealed class Singleton
    {
        private static Singleton instance = null;

        //程序运行时创建一个静态只读的进程辅助对象
        private static readonly object padlock = new object();
        private Singleton() { }

        public static Singleton Instance()
        {
            if (instance==null)
            {
                lock (padlock)  //在同一个时刻加了锁的那部分程序只有一个进程可以进入。
                {
                    if (instance == null)
                    {
                        instance = new Singleton();

                    }
                    

                }
                
            }
            return instance;

        }

    }
}

双重锁定是解决当instance为null时,同时有两个线程调用Instance()方法时,它们都可以通过instance==null的判断,然后只有一个线程进入,另一个在外排队等候,如果没有第二层instance=null的判断,第一个线程创建了实例,而第二个线程在等待创建实例,违背了单例模式的初衷。

 

以上代码同时也展示了静态初始化。

 

instance变量标记为readonly,只能是在静态初始化期间或者在类构造函数中分配变量。

这种静态初始化的方式是在自己被加载是就将自己实例化------恶汉式单例类。

要是在第一次被引用是,才会将自己实例化------------------懒汉式单例类。

 

本文版权归本人和博客园共同所用,转载请注明出处。

posted @ 2012-06-05 15:25  Cooper_Liu  阅读(244)  评论(0编辑  收藏  举报