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

本人在 横刀天笑 的一篇谈论单例模式的文章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,一经查实,立即删除!

相关文章

汇编Ring 3下实现 HOOK API

【文章标题】汇编ring3下实现HOOK API 【文章作者】nohacks(非安全,hacker0058) 【作者主页】hacker0058.ys168.com 【文章出处】看雪论坛(bbs.pediy.com) [ 汇编ring3下实现HOOK API ] Author: nohacks …

CSS之window的视图属性

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

[Linux C]递归遍历指定目录,以目录树形式展示

/*功能&#xff1a;演示了利用C语言递归遍历指定目录下的子目录(不含隐藏目录)和文件&#xff0c;并以目录树形式展示!其中编译命令为&#xff1a;gcc -o travel travel.c -stdc99*/#include <stdio.h>#include <dirent.h>#include <stdlib.h>#include <s…

在SQL Server2005中进行错误捕捉

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

ListT用法

List<T>和List的用法是一模一样的,不同的是,List支持任何类型而List<T>只支持T类型,T是在定义时指定的类型. 如: List<string> listnew List<string>; 这样的话,每个list里的元素都是字符串. 同理, List<int> listnew List<int>; 这样的话…

reduce

reduce reduce(callback,initiaValue)会传入两个变量&#xff0c;回调函数(callback)和初始值(initiaValue)。1.只传回调函数 prev只取数组的第一个元素 next从数组的第二个元素开始一直往下取var arr ["a", "b", "c", "d", "e&…

CSS之Screen视图属性

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

[Linux C]递归遍历指定目录下的子目录和文件

/*功能&#xff1a;演示了在Linux下利用C语言递归遍历指定目录下的子目录(不含隐藏目录)和文件*/#include <stdio.h>#include <dirent.h>#include <string.h>void List(char *path){struct dirent *ent NULL;DIR *pDir;if((pDir opendir(path)) ! NULL){wh…

Java的多进程运行模式分析

本文曾发表于天极网&#xff1a;http://dev.yesky.com/284/2659284.shtml一般我们在java中运行其它类中的方法时&#xff0c;无论是静态调用&#xff0c;还是动态调用&#xff0c;都是在当前的进程中执行的&#xff0c;也就是说&#xff0c;只有一个java虚拟机实例在运行。而有…

HDU 2594 Simpsons’ Hidden Talents (字符串-KMP)

Simpsons’ Hidden Talents Problem DescriptionHomer: Marge, I just figured out a way to discover some of the talents we weren’t aware we had.Marge: Yeah, what is it?Homer: Take me for example. I want to find out if I have a talent in politics, OK?Marge: …

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

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

[bash]删除文件中含特定字符串的行

]删除文件中含特定字符串的行[bash]: sed -e /abc/d a.txt // 删除a.txt中含"abc"的行&#xff0c;但不改变a.txt文件本身&#xff0c;操作之后的结果在终端显示 sed -e /abc/d a.txt > a.log // 删除a.txt中含"abc"的行&#xff0c;将操作之后的…

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

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

谈CRM产品设计的指导思想

客户关系管理&#xff08;CRM&#xff09;其本意强调的是对客户“关系”进行有效管理&#xff0c;从而达到维持较高的客户占有率&#xff08;customershare&#xff09;的目的。所谓关系&#xff0c;是指两个事物之间其中的一方对另一方的行为方式以及感受状态。所以&#xff0…

try catch finally

<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><title>try catch finally</title><script>// 异常最大的特征,就是一旦出现异常,后面的代码将不会再执行// 那为了保证后面的代码在出现异常之后…

Java笔记-IO流的运用

--如果朋友您想转载本文章请注明转载地址"http://www.cnblogs.com/XHJT/p/3877386.html "谢谢-- 1.InputStream和System.in&#xff08;Scanner&#xff09; InputStream 输出流以字节为单位来获取数据&#xff0c;且需要复杂的判断并创建字节数组作为缓冲 另外字节转…

[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 …