• 设计模式之-单例模式


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

    在我们平常的开发中,我们需要一些辅助类,比如Redis辅助类,一般把一些初始化的工作放在构造函数中,然后写一些方法来完成Redis要作的一些具体的功能。但是有一个问题,我们每次调用的时候都会去 实例化这个辅助类,然后去调用一些方法。然而每次实例化的时候构造函数里面作的事情都会被重复的做一遍。这与我们预期的并不符合。。。

    接下来我们来演示下怎样实现所谓的单例模式。

    1.单线程模式下实现单例

        public class Singleton
        {
            long lResult = 0;
            private Singleton()
            {
                Console.WriteLine("被实例化了一次");
                for (int i = 0; i < 100000000; i++)
                {
                    lResult += i;
                }
            }
            public long GetResult()
            {
                return lResult;
            }
            private static Singleton _singleton { get; set; }
            public static Singleton CreateInstance()
            {
                if (_singleton == null)
                {
                    _singleton = new Singleton();
                }
                return _singleton;
            }
        }

    调用:

        for (int i = 0; i < 10; i++)
        {
            Singleton singleton = Singleton.CreateInstance();
            Console.WriteLine(singleton.GetResult());
        }

    结果如下:

    2.多线程模式下实现单例

    我们来将调用的地方修改下:

        List<Task> tasks = new List<Task>();
        TaskFactory taskFactory = new TaskFactory();
        for (int i = 0; i < 10; i++)
        {
            tasks.Add(taskFactory.StartNew(() =>
            {
                Singleton singleton = Singleton.CreateInstance();
                Console.WriteLine(singleton.GetResult());
            }));
        }
        Task.WaitAll(tasks.ToArray());

    来看看我们将得到结果是什么:

    从上面的结果可以看出,第一次只能用于单线程的模式下,多线程下并不行。那么怎样才能让多线程下也可以实现单例呢?

    我们只需要修改下辅助类内部即可(用lock来实现)。

    修改后的代码:

    public class Singleton
        {
            private static object singleton_lock = new object();
            long lResult = 0;
            private Singleton()
            {
                Console.WriteLine("被实例化了一次");
                for (int i = 0; i < 100000000; i++)
                {
                    lResult += i;
                }
            }
            public long GetResult()
            {
                return lResult;
            }
            private static Singleton _singleton { get; set; }
            public static Singleton CreateInstance()
            {
                lock (singleton_lock)
                {
                    if (_singleton == null)
                    {
                        _singleton = new Singleton();
                    }
                }
                return _singleton;
            }
        }

    结果如下:

    上面就实现了我们的多线程下使用单例,当然上面的代码我们还是可以优化下,在lock之前,我们可以再用一个 if (_singleton == null) 来判断一下,至于为什么,自己思考下应该就明白了。

    3.使用静态构造函数

    辅助类内部代码:

        public class SingletonSecond
        {
            private static object singletonSecond_lock = new object();
            long lResult = 0;
            private SingletonSecond()
            {
                Console.WriteLine("被实例化了一次");
                for (int i = 0; i < 100000000; i++)
                {
                    lResult += i;
                }
            }
            public long GetResult()
            {
                return lResult;
            }
            private static SingletonSecond _singletonSecond { get; set; }
            static SingletonSecond()
            {
                _singletonSecond = new SingletonSecond();
            }
            public static SingletonSecond CreateInstance()
            {
                return _singletonSecond;
            }
        }

    调用:

        List<Task> tasks = new List<Task>();
        TaskFactory taskFactory = new TaskFactory();
        for (int i = 0; i < 10; i++)
        {
            tasks.Add(taskFactory.StartNew(() =>
            {
                SingletonSecond singleton = SingletonSecond.CreateInstance();
                Console.WriteLine(singleton.GetResult());
            }));
        }
        Task.WaitAll(tasks.ToArray());

    结果如下:

    4.静态对象

    内部代码:

        public class SingletonThird
        {
            private static object singletonSecond_lock = new object();
            long lResult = 0;
            private SingletonThird()
            {
                Console.WriteLine("被实例化了一次");
                for (int i = 0; i < 100000000; i++)
                {
                    lResult += i;
                }
            }
            public long GetResult()
            {
                return lResult;
            }
            private static SingletonThird _singletonThird = new SingletonThird();
            public static SingletonThird CreateInstance()
            {
                return _singletonThird;
            }
        }

    调用代码:

        List<Task> tasks = new List<Task>();
        TaskFactory taskFactory = new TaskFactory();
        for (int i = 0; i < 10; i++)
        {
            tasks.Add(taskFactory.StartNew(() =>
            {
                SingletonThird singleton = SingletonThird.CreateInstance();
                Console.WriteLine(singleton.GetResult());
            }));
        }
        Task.WaitAll(tasks.ToArray());

    结果如下:

    以上三种方式都可以用来实现单例模式。当然还有别的更多的方式,这里只是举一些例子学习用。

    源码:https://github.com/houzhenhuang/DesignPattern

  • 相关阅读:
    在oracle中通过connect by prior来实现递归查询!
    c# System.Data.OracleClient需要Oracle客户端软件8.1.7或更高版本
    c# 水晶报表的设计(非常的基础)
    webapi+EF(增删改查)
    简单三层分页aspnetpager控件(欢迎指点)
    listbox 多选删除(找了好多都不行,终于让我写出来了)
    execl导出(HTML,repearter控件)
    SQL Server中截取字符串常用函数
    几个经常用到的字符串的截取
    gridview的增删改
  • 原文地址:https://www.cnblogs.com/hhzblogs/p/10343531.html
Copyright © 2020-2023  润新知