码迷,mamicode.com
首页 > 其他好文 > 详细

单例模式

时间:2016-08-01 12:16:31      阅读:142      评论:0      收藏:0      [点我收藏+]

标签:

单例模式简介:

单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类只有一个实例。

单例模式结构图:

技术分享

1. 经典模式:

技术分享
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication3
{
    /// <summary>
    /// 一、经典模式:
    /// </summary>
    public class Singleton
    {
        /// <summary>
        /// Singleton的构造函数必须是私有的,以保证客户程序不会通过new()操作产生一个实例,达到实现单例的目的;
        /// </summary>
        private Singleton(){ }

        /// <summary>
        /// 私有的静态全局变量instance来保存该类的唯一实例;
        /// </summary>
        private static Singleton instance;

        /// <summary>
        /// 提供一个全局函数访问获得该实例,并且在该函数提供控制实例数量的功能,
        /// 即通过if语句判断instance是否已被实例化,
        /// 如果没有则可以同new()创建一个实例;
        /// 否则,直接向客户返回一个实例
        /// </summary>
        /// <returns></returns>
        public static Singleton GetInstance()
        {
            if (instance == null)
            {
                instance = new Singleton();
            }
            return instance;
        }

        /// <summary>
        /// 测试属性
        /// </summary>
        public int Age { get; set; }

        public void GetShow()
        {
            this.Age = this.Age + 1;
            Console.WriteLine("我是一个单例对象:Age=" + Age);
        }
    }
}
View Code

1)该Singleton的构造函数必须是私有的,以保证客户程序不会通过new()操作产生一个实例,达到实现单例的目的;

2)因为静态变量的生命周期跟整个应用程序的生命周期是一样的,所以可以定义一个私有的静态全局变量instance来保存该类的唯一实例;

3)必须提供一个全局函数访问获得该实例,并且在该函数提供控制实例数量的功能,即通过if语句判断instance是否已被实例化,如果没有则可以同new()创建一个实例;否则,直接向客户返回一个实例。

在这种经典模式下,没有考虑线程并发获取实例问题,即可能出现两个线程同时获取instance实例,且此时其为null时,就会出现两个线程分别创建了instance,违反了单例规则。因此,需对上面代码修改。

2.多线程下的单例模式: lazy模式

技术分享
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication3
{
    /// <summary>
    /// 二、多线程下的单例模式
  /// 1、Lazy模式
    /// </summary>
    public class Singleton2
    {
        private static Singleton2 instance2;
        private static object _lock = new object();

        private Singleton2()
        {

        }

        public static Singleton2 GetInstance(string thnum)
        {
            //外层的if语句块,这使得每个线程欲获取实例时不必每次都得加锁,
            //因为只有实例为空时(即需要创建一个实例),才需加锁创建,
            //若果已存在一个实例,就直接返回该实例,节省了性能开销
            if (instance2 == null)
            {
                //Console.WriteLine("object is null" + thnum);
                lock (_lock) 
                {
                    //内层的if语句块,使用这个语句块时,先进行加锁操作,
                    //保证只有一个线程可以访问该语句块而保证只创建了一个实例
                    if (instance2 == null)
                    {
                        //Console.WriteLine("object not null" + thnum);
                        instance2 = new Singleton2();
                        instance2.Age = 0;
                    }
                }
            }
            return instance2;
        }

        /// <summary>
        /// 测试属性
        /// </summary>
        public int Age { get; set; }

        public void GetShow(string thnum)
        {
            this.Age = this.Age + 1;
            Console.WriteLine("我是一个单利对象:Age=" + Age+" 线程:"+thnum);
        }

    }
}
View Code

上述代码使用了双重锁方式较好地解决了多线程下的单例模式实现。

内层的if语句块,使用这个语句块时,先进行加锁操作,保证只有一个线程可以访问该语句块,进而保证只创建了一个实例。

外层的if语句块,这使得每个线程欲获取实例时不必每次都得加锁,因为只有实例为空时(即需要创建一个实例),才需加锁创建,若果已存在一个实例,就直接返回该实例,节省了性能开销。

2.多线程下的单例模式: 饿汉模式

技术分享
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication3
{
    /// <summary>
    /// 二、多线程下的单例模式
    /// 2、饿汉模式
  /// 这种模式的特点是自己主动实例。
    /// </summary>
    public class Singleton3
    {
        /// <summary>
        /// 主动实例
        /// </summary>
        private static readonly Singleton3 instance = new Singleton3();

        private Singleton3()
        {

        }

        public static Singleton3 GetInstance()
        {
            return instance;
        }
    }
}
View Code

3.测试单例模式:

技术分享
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {

            Console.WriteLine("一、经典模式:测试");
            //Singleton s = new Singleton(); Error 编译器检测出现错误
            Singleton s = Singleton.GetInstance();
            s.GetShow();
            Singleton s1 = Singleton.GetInstance();
            s1.GetShow();
            Singleton s12 = Singleton.GetInstance();
            s12.GetShow();

            Console.WriteLine("二、多线程下的单例模式>Lazy模式:测试");
            Thread thr1 = new Thread(x => {
                Singleton2 s2 = Singleton2.GetInstance("thr1");
                s2.GetShow("thr1");
                s2.GetShow("thr1");
            });
            thr1.Start();
            Thread thr2 = new Thread(x => {
                Singleton2 s22 = Singleton2.GetInstance("thr2");
                s22.GetShow("thr2");
            });
            thr2.Start();
            Console.Read();
        }
    }
}
View Code

技术分享

 

单例模式

标签:

原文地址:http://www.cnblogs.com/heyangyi/p/5724991.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!