美文网首页
C#设计模式之单例模式

C#设计模式之单例模式

作者: Memoyu | 来源:发表于2019-04-21 16:25 被阅读0次
文章参考来源:http://www.cnblogs.com/zhili/p/SingletonPatterm.html
感谢:Learning hard

认知尚浅,如有错误,愿闻其详!

解析单例模式

单例模式作用在于保证让一个类只有一个实例对象。单例模式的实现过程就是一个控制它的方法。

1、例子

比如我们电脑中的任务管理器,同一时间内只允许一个实例对任务管理器中的进程进行操作。
(我们下面用创建单例窗口来展示)

这里为什么定义为静态的呢?对于这个疑问的解释为:每个线程都有自己的线程栈,定义为静态主要是为了在多线程确保类有一个实例

3、例子实现方式一(不推荐):具体实现是将构造方法( Window1())私有化,提供一个访问它的全局静态访问点(GetInstance()方法)来创建实例对象,返回对象。

(在以该单例实现中,如果我们手动关闭了单例窗口,再次按下弹出窗口时,会报异常,源于该实例已经销毁,但是主窗口仍然尝试调用。所以关闭窗口后应将实例置为null)

 public partial class Window1 : Window
    {
        private static Window1 singletonWin;//静态变量用来存储类的实例
        /// <summary>
        /// 私有化构造函数,以保证外部无法再次实例化对象
        /// </summary>
        private Window1()
        {
            InitializeComponent();
            this.Closing += Window1_Closing;//关闭窗口事件
        }


        /// <summary>
        /// 类中的全局访问点。
        /// </summary>
        /// <returns>返回实例对象</returns>
        public static Window1 GetInstance()
        {
            if (singletonWin == null)//判断类是否已经实例化
            {
                singletonWin = new Window1();
            }
            return singletonWin;
        }
        /// <summary>
        /// 在以上单例实现中,如果我们手动关闭了单例窗口,再次按下弹出窗口时,会报异常,源于该实例已经销毁,但是主窗口仍然尝试调用。所以关闭窗口后应将实例置为null
        /// </summary>
        private void Window1_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            singletonWin = null;//置空
        }
4、例子实现方式二(推荐):为了解决方式一存在的线程安全问题,添加了一个标识(locker())和线程锁语句(lock{})来确保线程同步。解决过程如下:

假设,当前有多个线程调用该方法。

  • 当第一个线程运行到此处时,线程会对locker对象进行加锁
  • 第二个线程运行到此处时,首先会检测locker对象的状态(是否加锁),如果加锁,则会刮起,等待第一个线程执行完毕解锁
  • lock语句执行完成后(即线程执行完毕)会进行该对象的解锁。
 private static readonly object locker = new object();//定义一个标识确保线程同步
        /// <summary>
        /// 类中的全局访问点。加入线程锁
        /// </summary>
        /// <returns>返回实例对象</returns>
        public static Window1 GetInstanceLock()
        {
            //////////////////////////////////////
            ///假设,当前有多个线程调用该方法。
            ///当第一个线程运行到此处时,线程会对locker对象进行加锁
            ///第二个线程运行到此处时,首先会检测locker对象的状态(是否加锁),如果加锁,则会刮起,等待第一个线程执行完毕解锁
            ///lock语句执行完成后(即线程执行完毕)会进行该对象的解锁。
            /////////////////////////////////////
            ///为了避免锁所增加的额外性能开销,我们需要额外添加一个判断(if (singletonWin == null)),这个称为双重锁定。
            if (singletonWin == null)//双重锁定只需要一句判断就可以了
            {
                lock (locker)//线程锁
                {
                    if (singletonWin == null)//判断类是否已经实例化
                    {
                        singletonWin = new Window1();
                    }
                }
            }
            return singletonWin;
        }

(以上为单例窗口代码)

代码

主窗口代码

        public MainWindow()
        {
            InitializeComponent();
            btnSingleton.Click += BtnSingleton_Click;//注册点击事件
        }
        /// <summary>
        /// 按钮点击事件
        /// </summary>
        private void BtnSingleton_Click(object sender, RoutedEventArgs e)
        {
            //Window1 win1 = Window1.GetInstance();//方式一创建窗口,存在线程安全问题
            //win1.Show();
            //win1.Focus();//获取焦点

            Window1 win = Window1.GetInstanceLock();//方式二,添加线程锁,解决线程安全问题
            win.Show();
            win.Focus();

        }
    }

展示

SingletonPattern.gif

相关文章

网友评论

      本文标题:C#设计模式之单例模式

      本文链接:https://www.haomeiwen.com/subject/cywlgqtx.html