资深工程师为何否定这种单例模式

本人在 横刀天笑 的一篇谈论单例模式的文章http://www.cnblogs.com/yuyijq/archive/2007/10/07/915941.html
里面有两种写单例的例子.有一种方法得到资深工程师的否定.事实证明他的想法是错误的。
 
   第一种:

    public class Singleton
 2{
 3    private static Singleton _instance = null;
 4    private static readonly object lockHelper = new object();
 5    private Singleton()
 6    {
 7    }

 8    public static Singleton CreateInstance()
 9    {
10        //这样lock以及lock块内的代码只会在第一次调用CreateInstance方法的时候执行,
11        //第一次调用该方法后_instance就不再为null了,if块内的代码就无须执行了
12        if(_instance == null)
13        {
14            lock(lockHelper)
15            {
16                if(_instance == null)
17                    _instance = new Singleton();
18            }

19        }

20        return _instance;
21    }

22}

      这种方法也是大家公认的能够在多线程下面正常工作的一种方法.

      原文中还提到了一种方法:

     实际上在很多地方我们可以采用另外一种初始化的方式,特别对于哪些实时系统或者哪些系统随时都会用的类(比如系统配置类),我们用另外一种实现方法就不需要考虑线程安全的问题了,它们的线程安全由.net运行时为我们作保证。

 

 1public class Singleton
 2{
 3    //先实例化出一个实例再说
 4    private static Singleton _instance = new Singleton();
 5        private Singleton(){}
 6    public static Singleton CreateInstance()
 7    {
 8        return _instance;
 9    }

10}

    博主说这两种方法都可以,我自己也不太清楚它们之间的区别,但是本人记忆力好,记下了.

    一次在中软面试中,有一个题让你写一个单例模式例子出来,我想都没想就把上面第二种方法写出来了,当然我忘了写私有构造函数.这个也不影响思路.但是他们的技术人员说这不是单例模式,因为每次初始化类的时候就会new一次.
private static Singleton _instance = new Singleton();他可能是说这个.

   之后我亲自测试了下博主说的第二种方法,说明是可行的,并非多线程.起码单线程是可以的.
   
   我想他的意思应该是这样的:
  
public class Singleton2
    
{
        
//先实例化出一个实例再说
        private static Singleton2 _instance = null ;
        
private DateTime _stime;
        
public DateTime sTime
        
{
            
get return this._stime; }
            
set this._stime = value; }

        }

        
private Singleton2()
        
{
            
this.sTime = DateTime.Now;

        }

        
public static Singleton CreateInstance()
        
{
            
if (_instance == null)
            
{
                
return new Singleton2();

            }

            
else
            
{
                
return _instance;
            
            }

            
        }

    }
     
     经过我的测试,第三种代码是不正确的.

     我在MSDN上查了关于static的解释:

     static
    修饰符指明成员属于类本身而不属于类的实例。即使创建了类的多个实例,给定应用程序中只存在 static 成员的一个副本。您只能通过对类的引用(而不是对实例的引用)来访问 static 成员。但是,在类成员声明中,可以通过 this 对象来访问 static 成员。
    类的成员可以使用 static 修饰符来标记。类、接口和接口的成员不能采用 static 修饰符。不能将 static 修饰符与任何继承修饰符(abstract 和 final)或版本安全修饰符(hide 和 override)组合。

     这就说明了博主的说法是正确的,无论初始化多少次类,但是只会存在静态成员的一个副本.
     据说那个面试官是特别资深的工程师,他应该也有他的理由说那不是单例,我想让大家给说说第二种代码是否是真正的单例模式. 

     谢谢大家对的帮助,今天回家看了下《HEAD FIRST 设计模式》在P181中明确的说明了上文中的第二种方法是可行的,也是真正的单例模式:

     原文是这样的:

     2。使用“急切”创建实例,页不用延迟实例化的做法
     如果应用程序总是创建并使用单件实例,或者在创建和运行时方面的负担不太繁重,你可能想要急切(eagerly)创建此单件,如下所示:
     代码和上文中第二种方法是一模一样的。还特意对:private static Singleton _instance = new Singleton();这条语句进行说明:
     在静态初始化器中创建单件,这段代码保证了线程安全。

     本文中第一种创建单件的方法属于延迟实例化的做法,只有当第一次调用的时候才会实例化类,没有用到时则不进行任何实例化操作。所有说当类实例化不是特别复杂,对服务器开销不大的时候这两种方法在最终作用上和效果上是一样的,没有本质区别。所以最后本人认为我面试中的面试官的观点是错误的。如果有理解错误的地方还望指点。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/407484.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CSS之window的视图属性

1. innerWidth 属性和innerHeight 属性 innerWidth获取浏览器窗口宽度,注意不带浏览器的边框宽度,但是包括下拉按钮的宽度 innerHeight获取浏览器窗口高度,从浏览器底部到工具栏的距离,注意不包括工具栏的高度 innerWidth和inner…

在SQL Server2005中进行错误捕捉

任何程序都可能出现错误,在SQL Server中执行Transact-SQL也不例外。如果在Transact-SQL中发生了错误,一般有两种捕捉错误的方法,一种是在客户端代码(如 c#、delphi等)中使用类似try...catch的语句进行捕捉;另外一种就是…

CSS之Screen视图属性

1.availWidth和availHeight availWidth和availHeight返回的是显示器可用宽高,注意不包括开始菜单栏这种东东的高度和宽度 2.colorDepth 表示显示器的颜色深度 3.width和height 表示显示器屏幕的宽高,和availWidth和availHeight的区别是返回的宽高包含…

微信小程序几种常用弹窗提示

第一种:弹出提示框,可以选择确定或者取消。 代码:wx.showModal({title: 提示,content: 这是一个模态弹窗,success: function (res) {if (res.confirm) {//这里是点击了确定以后console.log(用户点击确定)} else {//这里是点击了取消以后conso…

CSS之文档视图(DocumentView)和元素视图(ElementView)方法

1.elementFromPoint() 返回给定坐标处的元素。是个在目前而言,兼容性不错的方法 将给定位置处(100,100)的元素的字体颜色设置为红色 2.getBoundingClientRect() 返回的是返回的是一个对象,包含 top, left, right, 和 bottom四个属性值,大小…

[Bash]kill指定的进程名

通过bash来kill指定的进程名&#xff0c;bash文件名为&#xff1a;/home/zcm/bin/d.sh&#xff0c;内容如下&#xff1a; #!/bin/shif [ "$1" "" ]; thenecho "Usage: sh $0 <processname>"exit 0fi#s1ps -ef|grep $1|grep -v grep|awk …

CSS之元素视图属性

1.clientLeft和clientTop 返回的是内容区域的左上角相对于整个元素左上角的位置&#xff08;包括边框&#xff09; 2.clientWidth和clientHeight 表示内容区域的高度和宽度&#xff0c;包括padding大小&#xff0c;但是不包括边框和滚动条 3.offsetLeft和offsetTop offsetLe…

Vue之Vue.set动态新增对象属性

当我们给一个比如props中&#xff0c;或者data中被观测的对象添加一个新的属性的时候&#xff0c;不能直接添加&#xff0c;必须使用Vue.set方法 Vue.set方法用来新增对象的属性。如果要增加属性的对象是响应式的&#xff0c;那该方法可以确保属性被创建后也是响应式的&#x…

Vue之过渡动画

v-enter: 定义过渡开始时元素的状态。在元素被插入时生效&#xff0c;在下一个帧(下一帧也就是v-enter-active)移除(实际就是过渡将要开始之前&#xff0c;元素的状态) v-enter-active: 定义”进入过渡”的结束状态。在元素被插入时生效&#xff0c;在 transition/animation 完…

AppleScript快速入门教程

基础语法 AppleScript 入门 一、这部分介绍注释,发出声音,弹窗 (1)简单入门 <1>多行注释 (* this is multi comment *) <2>发出响声beep 3(2)#表示使用"Daniel"(英国发音)发出声音,人员选择如下图1所示say "Hello,world" using "Daniel&…

CSS之EM属性

什么是EM&#xff1f; 在一个空白的HTML文档内&#xff0c;你没有任何关于字体大小的声明而只使用默认设置。在大多数浏览器上为html和body标签的默认字体大小为100% 使用EM为单位一定要知道父元素的设置&#xff0c;因为EM是一个相对值&#xff0c;是一个相对于父元素的值 如…

PyQt6 QTimer计时器控件

锋哥原创的PyQt6视频教程&#xff1a; 2024版 PyQt6 Python桌面开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili2024版 PyQt6 Python桌面开发 视频教程(无废话版) 玩命更新中~共计52条视频&#xff0c;包括&#xff1a;2024版 PyQt6 Python桌面开发 视频教程(无废话版…

前台关于跨域的警告A cookie associated with a cross-site resource at .........,代理服务器

前台关于跨域的警告A cookie associated with a cross-site resource at …&#xff0c;代理服务器 A cookie associated with a cross-site resource at … 解决该警告的方法&#xff1a; 在配置文件中添加配置如下&#xff1a; "proxy": {"/api": {&quo…