C# 设计模式巩固 - 单例模式

 前言

  设计模式的文章很多,所以此文章只是为了巩固一下自己的基础,说的不详细请见谅。

 介绍 - 单例模式

  官方定义:确保一个类只有一个实例,并提供一个全局访问点。

  通俗定义:就是一个类只有一个单个实例。(也没啥区别)

 实现

  如何保证一个类只有一个实例呢?

  1. 首先一个类是如何创建实例的? - 通过构造函数

  2. 如何保证只创建一个呢? - 构造函数只执行一次

  3. 如何保证构造函数只执行一次呢? - 访问外部类无权访问

  4. 如何让访问外部类无权访问? - 私有方法

  问题解决,上代码:

    /// <summary>
    /// 单例类
    /// </summary>
    public class Singleton
    {
        /// <summary>
        /// 私有构造函数
        /// </summary>
        private Singleton() { }
        /// <summary>
        /// 单例字段
        /// </summary>
        private static Singleton _instance; 
        /// <summary>
        /// 单例对象
        /// </summary>
        public static Singleton Instance
        {
            get
            {
                if (_instance == null)
                    _instance = new Singleton();
                return _instance;
            }
        }

        /// <summary>
        /// 输出
        /// </summary>
        public void WriteLine()
        {
            Console.WriteLine("哈希Code : " + this.GetHashCode());
        }
    }

测试输出 HashCode :

  class Program
    {
        static void Main(string[] args)
        {
            Singleton.Instance.WriteLine();
            Singleton.Instance.WriteLine();
            Singleton.Instance.WriteLine();
            Console.Read();
        }
    }

结果:

这样就结束了吗? -(身为C#老鸟的我还要考虑下线程安全的问题,考虑并发的情况)

我们需要构建一个并发的情形及多条线程同时创建对象,下面我就用简单粗暴的方法,需要对单例进行修改:

        /// <summary>
        /// 单例对象
        /// </summary>
        public static Singleton Instance
        {
            get
            {
                if (_instance == null)
                {
                    Thread.Sleep(1);
                    _instance = new Singleton();
                }
                return _instance;
            }
        } 

调用测试:

class Program
    {
        static void Main(string[] args)
        {
            //线程1
            Thread thread1 = new Thread(new ThreadStart(() =>
            {
                Singleton.Instance.WriteLine();
            }));
            //线程2
            Thread thread2 = new Thread(new ThreadStart(() =>
            {
                Singleton.Instance.WriteLine();
            }));
            //线程3
            Thread thread3 = new Thread(new ThreadStart(() =>
            {
                Singleton.Instance.WriteLine();
            }));
            thread1.Start();
            thread2.Start();
            thread3.Start();
            Console.Read();
        }
    }

输出结果:

所以我们要对代码进行改进(加锁):

/// <summary>
    /// 单例类
    /// </summary>
    public class Singleton
    {
        /// <summary>
        ////// </summary>
        private static object locker = new object();
        /// <summary>
        /// 私有构造函数
        /// </summary>
        private Singleton() { }
        /// <summary>
        /// 单例字段
        /// </summary>
        private static Singleton _instance;
        /// <summary>
        /// 单例对象
        /// </summary>
        public static Singleton Instance
        {
            get
            {
                lock (locker)
                {
                    if (_instance == null)
                    {
                        Thread.Sleep(1);
                        _instance = new Singleton();
                    }
                }
                return _instance;
            }
        }

        /// <summary>
        /// 输出
        /// </summary>
        public void WriteLine()
        {
            Console.WriteLine("哈希Code : " + this.GetHashCode());
        }
    }

测试结果:

解决!

锁是个好东西但是要慎用,它是很耗资源的。所以还需要对代码进行改进,看代码我们知道只有 _instancenull 时才需要考虑并发加锁,所以我们再次改进:

    /// <summary>
    /// 单例类
    /// </summary>
    public class Singleton
    {
        /// <summary>
        ////// </summary>
        private static object locker = new object();
        /// <summary>
        /// 私有构造函数
        /// </summary>
        private Singleton() { }
        /// <summary>
        /// 单例字段
        /// </summary>
        private static Singleton _instance;
        /// <summary>
        /// 单例对象
        /// </summary>
        public static Singleton Instance
        {
            get
            {
                if(_instance == null)
                {
                    lock (locker)
                    {
                        if (_instance == null)
                        {
                            Thread.Sleep(1);
                            _instance = new Singleton();
                        }
                    }
                }
                return _instance;
            }
        }

        /// <summary>
        /// 输出
        /// </summary>
        public void WriteLine()
        {
            Console.WriteLine("哈希Code : " + this.GetHashCode());
        }
    }

欢迎批评指正!转载请注明出处:http://www.cnblogs.com/xinwang/p/6294784.html 

 

posted @ 2017-01-17 21:21  CharlesShang  阅读(207)  评论(0编辑  收藏  举报