(5)创建型模式——单例

创建型模式——单例(Singleton)

问题背景

当某个类的实例只需要有一个或只能有一个时,通常有两种做法。一是直接使用静态类,这是一种面向过程的做法,它的优点是实现和使用比较方便,但这种做法无法享受到面向对象机制带来的好处;另一种做法是使用单例类,将构造方法设为私有并在内部保证全局只有一个实例。假设在一局游戏中存在一个单位管理器类UnitManager,这个类负责管理这局游戏中的所有单位。显然UnitManager类只能存在一个实例,所有有关单位的操作都要通过这个实例进行。如果存在多个实例,就会破坏数据的一致性。

解决方案

保证只有一个实例的方法很简单,只需要将所有构造方法设为私有即可。如此一来,外界无法用面向对象的方式创建该类的实例(如果出于某种目的想报复领导可以用反射233……),而内部创建一个实例并提供全局访问点,就达到了单例的目的。单例类的标准形式是这样的:
程序结构
根据需要,可以使用延迟加载、同步锁等功能来增强单例类。

所谓延迟加载,就是将单例的创建延迟到程序第一次访问时,这样做可以避免单例类在未被使用时占用内存。如果在多线程系统中使用了延迟加载,就需要使用同步锁保证单例创建时的数据一致性。

效果

  1. 保证了全局只有一个实例。
  2. 可以控制单例加载的时机。
  3. 可以使用面向对象的特性。
  4. “单例”的意义并不仅仅限于“一个”实例,任意有穷数量的实例都可以认为是“单例”。

缺陷

一般情况下,单例类应该设计成无状态的。无论如何,单例类的本质还是全局变量。如果系统的两处需要用到同一个单例的不同状态,则很容易造成数据不一致,如果存在多个线程,就更容易出错。全局变量会带来很多麻烦,这在POP盛行的时期就已经是不争的事实。如果一定要使用全局变量,最好设置为只读。

如果真的出现了有状态的单例类,可以尝试将其分解为多个无状态的单例类。

相关模式

创建型模式中的其他模式都可以设计成单例类。

实现

using System;

namespace Singleton
{
    class Client
    {
        public class UnitManager
        {
            private static UnitManager inst;
            private static object instLock = new object();
            public static UnitManager Instance
            {
                get
                {
                    lock (instLock)
                    {
                        if (inst == null)
                        {
                            Instance = new UnitManager();
                        }
                    }
                    return inst;
                }
                private set
                {
                    inst = value;
                }
            }
            private UnitManager()
            {
                Console.WriteLine("UnitManager已初始化");
            }
            public void Show()
            {
                Console.WriteLine("我是线程安全的延迟加载单位管理器");
            }
        }

        static void Main(string[] args)
        {
            Console.WriteLine("程序启动...");
            Console.WriteLine("访问线程安全单位管理器");
            UnitManager.Instance.Show();
        }
    }
}

运行结果

发布了9 篇原创文章 · 获赞 10 · 访问量 264

猜你喜欢

转载自blog.csdn.net/DIAX_/article/details/104152684