单件型模式(Singleton Pattern)


概述
Singleton模式要求一个类有且仅有一个实例,并且提供了一个全局的访问点。这就提出了一个问题:如何绕过常规的构造器,提供一种机制来保证一个类只有一个实例?客户程序在调用某一个类时,它是不会考虑这个类是否只能有一个实例等问题的,所以,这应该是类设计者的责任,而不是类使用者的责任。


意图
保证一个类仅有一个实例,并提供一个访问它的全局访问点。

例子
1.ASP.NET某应用程序对应的Application必须是唯一的。
2.不管在什么时候谈到地球,它都是指同一个地球。
3.某全局计数器对象是必须是唯一的,否则会使计数失败。

UML类图


代码:对应UML类图
 1    /// <summary>
 2    /// UML类图对应单件类
 3    /// </summary>

 4    public class Singleton
 5    {
 6        private static Singleton instance;
 7
 8        private Singleton() { }
 9
10        public static Singleton Instance
11        {
12            get
13            {
14                if (instance == null)
15                {
16                    instance = new Singleton();
17                }

18                return instance;
19            }

20        }

21    }

 1    /// <summary>
 2    /// UML类图对应客户端程序类
 3    /// </summary>

 4    public class MainApp
 5    {
 6        public static void Main()
 7        {
 8            Singleton s1 = Singleton.Instance;
 9            Singleton s2 = Singleton.Instance;
10
11            if (s1 == s2)
12            {
13                Console.WriteLine("Object are the same instance");
14            }

15
16            Console.Read();
17        }

18    }

代码:六种实现方式
 1.最简单的实现,但不支持线程安全
 1 /// <summary>
 2    /// 最简单的单件模式
 3    /// 不支持多线程安全
 4    /// </summary>

 5    public class Singleton1
 6    {
 7        private Singleton1() { }
 8
 9        private Singleton1 instance = null;
10
11        public Singleton1 Instance
12        {
13            get
14            {
15                if (this.instance == null)
16                {
17                    this.instance = new Singleton1();
18                }

19                return this.instance;
20            }

21        }

22    }

 2.支持线程安全,但是不支持多线程的并发操作
 1    /// <summary>
 2    /// 线程安全
 3    /// 但不支持线程并发
 4    /// </summary>

 5    public class Singleton2
 6    {
 7        private Singleton2() { }
 8
 9        private Singleton2 instance = null;
10
11        private static object objLock = new object();
12
13        public Singleton2 Instance
14        {
15            get
16            {
17                lock (objLock)
18                {
19                    if (this.instance == null)
20                    {
21                        this.instance = new Singleton2();
22                    }

23                }

24                return this.instance;
25            }

26        }

27    }

 3.支持线程安全,使用双检查(Double Check),支持多线程的并发操作
 1/// <summary>
 2    /// 线程安全
 3    /// 支持线程并发
 4    /// </summary>

 5    public class Singleton3
 6    {
 7        private Singleton3 instance = null;
 8
 9        private Singleton3() { }
10
11        private static object objLock = null;
12
13        public Singleton3 Instance
14        {
15            get
16            {
17                if (this.instance == null)
18                {
19                    lock (objLock)
20                    {
21                        if (this.instance == null)
22                        {
23                            this.instance = new Singleton3();
24                        }

25                    }

26                }

27                return this.instance;
28            }

29        }

30
31    }

 4.使用静态初始化方式,但不支持缓实例化
 1    /// <summary>
 2    /// 静态初始化
 3    /// 但不实现缓初始化
 4    /// </summary>

 5    public class Singleton4
 6    {
 7        private Singleton4() { }
 8
 9        private readonly static Singleton4 Instance = new Singleton4();
10    }

 5.使用静态初始化方式,且支持缓实例化,但引入了附加类
 1    /// <summary>
 2    /// 静态初始化
 3    /// 实现缓初始化
 4    /// </summary>

 5    public class Singleton5
 6    {
 7        private Singleton5() { }
 8
 9        public static Singleton5 Instance
10        {
11            get
12            {
13                return Nested.instance;
14            }

15        }

16
17        class Nested
18        {
19            private Nested() { }
20
21            internal readonly static Singleton5 instance = new Singleton5();
22        }

23    }

24


 6.使用静态初始化方式,且支持缓实例化,实际使用时首选
 1    /// <summary>
 2    /// 静态实例
 3    /// 实现缓初始化
 4    /// .NET下的首选方式
 5    /// </summary>

 6    public class Singleton6
 7    {
 8        private static Singleton6 instance;
 9
10        private Singleton6() { }
11
12        public static Singleton6 Instance
13        {
14            get
15            {
16                if (Singleton6.instance == null)
17                {
18                    Singleton6.instance = new Singleton6();
19                }

20                return instance;
21            }
            
22        }

23    }


代码:完整例子
  实现简单计数功能
 1 /// <summary>
 2    /// 计数器类
 3    /// </summary>

 4    public class SingletonCounter
 5    {
 6        /// <summary>
 7        /// 将构造函数置为私有
 8        /// </summary>

 9        private SingletonCounter() { }
10
11        private static SingletonCounter instance;
12
13        public static SingletonCounter Instance
14        {
15            get
16            {
17                // 缓实例化
18                if (instance == null)
19                {
20                    instance = new SingletonCounter();
21                }

22                return instance;
23            }

24        }

25
26        // 存放计数结构
27        private int num = 0;
28
29        // 计数
30        public void Add()
31        {
32            this.num++;
33        }

34
35        // 获取计数结果
36        public int GetNum()
37        {
38            return this.num;
39        }

40    }

 1    /// <summary>
 2    /// 执行计数类
 3    /// </summary>

 4    public class DoCounter
 5    {
 6        public void Counter()
 7        {
 8            SingletonCounter sc;
 9
10            for (int i = 0; i < 10; i++)
11            {
12                // 每次使用到计数器对象都重新赋值
13                sc = SingletonCounter.Instance;
14                sc.Add();
15                Console.WriteLine(sc.GetNum());
16            }

17        }

18    }

 1    /// <summary>
 2    /// 客户端
 3    /// </summary>

 4    public class MyApp
 5    {
 6        public static void Main()
 7        {
 8            DoCounter dc = new DoCounter();
 9            dc.Counter();
10
11            Console.Read();
12        }

13    }


总结
单件模式提供非常好的机制保证,实例唯一且有全局唯一访问点

 源代码:[下载]

参考
1. 【dofactory】ttp://www.dofactory.com/Patterns/Patterns.aspx#list
2. 【Terrylee】http://www.cnblogs.com/Terrylee/archive/2006/07/17/334911.html
3. 【卢振宇老师】http://zhenyulu.cnblogs.com/category/6930.html


原文地址:https://www.cnblogs.com/im/p/1127587.html