【C#设计模式-单例模式】

来源:互联网 发布:java 通过ip获取地址 编辑:程序博客网 时间:2024/05/29 19:55

单例模式就是保证在整个应用程序的生命周期中,在任何时刻,被指定的类只有一个实例,并为客户程序提供一个获取该实例的全局访问点


一:经典模式:

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);        }    }}

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

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

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

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

二.多线程下的单例模式:

1、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);        }    }}

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

内层的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;        }    }}

测试:

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();        }    }}



2 0
原创粉丝点击