设计模式详细系列教程 (四) 无处不在的单例模式

来源:互联网 发布:java小程序源代码 编辑:程序博客网 时间:2024/05/21 09:21

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

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

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

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

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

         【单例原理图】

        【单例代码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# 机制: 在第一次引用该类时实例化,第一种机制:在加载时实例化。

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

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

     

     

     

     

     

     

     

     

  • 原创粉丝点击