zoukankan      html  css  js  c++  java
  • 设计模式详细系列教程 (四) 无处不在的单例模式

              谈到单例模式很多人应该知道它的作用,用单例时主要有三个要点需要注意:

              一是某个类只能有一个实例;

              二是它必须自行创建这个实例;

              三是它必须自行向整个系统提供这个实例。

             那么它如何实现这样的功能呢?让我们先看一下单例模式图:

             【单例原理图】

            【单例代码C#】

    ///////////////////////////////////////////////////////////
    //  Singleton.cs
    //  Implementation of the Class Singleton
    //  Generated by Enterprise Architect
    //  Created on:      16-八月-2012 15:43:21
    //  Original author: 李龙生
    ///////////////////////////////////////////////////////////
    
    
    
    
    namespace Singleton {
    	public class Singleton {
    
    		private static Singleton instance;
    
    
    
    		~Singleton(){
    
    		}
    
    		public virtual void Dispose(){
    
    		}
    
    		/// <summary>
    		/// 私有构造函数,防止外部类实例化它
    		/// </summary>
    		private Singleton(){
    
    		}
    
    		/// <summary>
    		/// 全局访问点,返回本类实例
    		/// </summary>
    		public Instance GetInstance(){
    			
    			if (instance == null)
    			{
    				instance=new Singleton();
    			}
    
    			return null;
    		}
    
    	}//end Singleton
    
    }//end namespace Singleton

              

          【单例应用场景】

  • 需要频繁实例化然后销毁的对象。
  • 创建对象时耗时过多或者耗资源过多,但又经常用到的对象。
  • 有状态的工具类对象。
  • 频繁访问数据库或文件的对象。
  • 以及其他我没用过的所有要求只有一个对象的场景。
  • 例如资源管理器、打印机、通信端口等,它们也符合开头介绍的三个要点。

           

          【单例应用实例】

            我们刚做完机房收费系统,那它来举例说明,这个系统中有一个功能是在线人数的显示,在线人数是在系统运行期间就一直存在的,属于全局对象,并且时时更新,访问数据库,可以用单例模式让这个对象实例化一次,提高执行效率。

            同样,在我们看到的一些论坛、网站、CSDN、博客园等都有一种“在线用户人数”这一项功能,你是否知道这一功能是如何实现的,实现这个功能如果采用面向对象,每当有一个用户上线或者下线都会去实例化一个该对象,然后,像数据库或文件中插入删除数据,这就是单例模式场景的一种应用。

            实现该功能的代码 C#

    ///////////////////////////////////////////////////////////
    //  OnlineCounter.cs
    //  Implementation of the Class OnlineCounter
    //  Generated by Enterprise Architect
    //  Created on:      16-八月-2012 15:43:21
    //  Original author: 李龙生
    ///////////////////////////////////////////////////////////
    
    namespace OnlineCounter {
    	public class OnlineCounter {
            //私有属性,保存该类唯一实例
    		private static OnlineCounter instance;
            //私有属性,保存在线人数
            private int onlineCount = 0;
    
    		/// <summary>
    		/// 私有构造函数,防止外部类实例化它,并初始化onlineCount值
    		/// </summary>
    		private OnlineCounter(){
    
                //从文件或者数据库表中读取数据,设置默认为10
                this.onlineCount = 10;
    		}
            //用户登陆,在线人数加一
            public void IncreaseCount()
            {
                this.onlineCount++;
            }
            //用户下线,在线人数减一
            public void DecreaseCount()
            {
                this.onlineCount--;
            
            }
            //获取现在人数
            public int GetCount()
            {
                return onlineCount;
            }
    		/// <summary>
    		/// 全局访问点,返回本类实例
    		/// </summary>
    		public static OnlineCounter  GetInstance(){
    
                if ( instance == null )
                {
                    instance = new OnlineCounter();
                }
    
    			return instance;
    		}
    
    	}//end OnlineCounter
    
    }//end namespace OnlineCounter

                

                 【进一步优化】

               完美的人是不存在的,每个人对于完美的理解不同,当你觉的某某人好时,他可能是完美的。同样,完美的代码也不存在,上面代码解决了全局访问和实例化问题,却还有线程安全问题。

               带来线程安全主要是因为实例化的对象时,恰巧两个对象同时访问该类全局函数,创建它的对象,个人感觉这种同年同月同日生同时同秒出生的概率是很小的,不过,还是存在需要进行安全处理。

               给实例化对象部分的代码加锁:双重锁定

     

                    

           【C# 实现机制】

               C#实现同上面类似这里不再累述,不同的是C#没有安全问题,安全由CLR解决,下面给出简单代码:

    //阻止派生类发生,而派生类可能会增加实例
    public sealed class Singleton
    {
        //公共语言运行库负责初始化
        private static readonly Singleton instance = new Singleton();
        private Singleton()
        { 
        }
        public static Singleton GetInstance()
        {
            return instance;
        }
    
    }

             

           【懒汉与饿汉】

                懒汉与饿汉从表面上看是非常简单,饿汉就想快点吃,快点把食物实例化出来,而懒汉呢不着急,什么时候实例化食物都无所谓。

               用懒汉与饿汉比喻单例实例化时间的早晚,再恰当不过了。

               C# 机制: 在第一次引用该类时实例化,第一种机制:在加载时实例化。

               感觉这两种机制各有优缺点,但个人感觉对于很大的程序还是引用时实例化比较好,这样会占用少的系统资源,使空间合理利用。

               希望大家可以学好单例,但想掌握好单例模式,需要更多的实践和应用,只有在实践中才能成长!!!

     

     

     

     

     

     

     

     

查看全文
  • 相关阅读:
    4G DTU在城市景观照明中的应用解决方案
    物联网在物业管理和智慧楼宇中的应用解决方案
    4G工业路由器等物联网设备在食品安全检测中的应用
    NB-IoT网络在农业和畜牧业中的物联网智能灌溉应用案例
    串口服务器等应用于污水处理厂的自动监控和控制管理
    插卡式双卡4G工业路由器在数控机床远程控制中的应用
    4G工业路由器在水电站远程监控中的应用案例
    4G工业路由器在供水系统和道路交通远程检测中的应用案例
    HDU 6188 Duizi and Shunzi 贪心
    HDU 6185 Covering 矩阵快速幂
  • 原文地址:https://www.cnblogs.com/lilongsheng1125/p/4978631.html
  • Copyright © 2011-2022 走看看