随笔-90  评论-947  文章-0  trackbacks-0

我的观点可能有点激进,我觉得单件模式啥也不是,纯粹是个全局变量的贞洁牌坊而已。全局变量如果有必要,用就用了,何必伪装;如无必要,就算穿上单件模式的马甲,到头来也会搞得一片狼籍——随处可见GetInstance。

欢迎讨论~

posted on 2010-03-29 10:58 溪流 阅读(4397) 评论(63)  编辑 收藏 引用 所属分类: C++

评论:
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-29 11:43 | 空明流转
单间的实例限定和访问可控,你能global做到撒?尽白扯。  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-29 11:48 | 溪流
@空明流转
没白扯。
如果要限定单一实例,这个类实际上需要是个静态类。

访问可控?我就不懂了,,单件模式访问哪里可控?  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-29 12:21 | 陈梓瀚(vczh)
@空明流转
最容易的办法就是

[ShitOperator.h]

class IShitOperator
{
public:
virtual void DoShit()=0;
};

extern IShitOperator* GetShitOperator();

//--------------------------------------------------------
[ShitOperator.cpp]

class ShitOperator : public IShitOperator
{
..
} shitOperator;

IShitOperator* GetShitOperator()
{
return &shitOperator;
}

-------------------------------------------------------------

我TM就不知道一个单件哪来那么多问题,拿一个纯虚类一套,不管三七二十一你用没用到反正我在main之前先创建好了,还有那么多乱七八糟的锁啊,private constructor什么的干嘛呢。  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要?[未登录] 2010-03-29 12:34 | x
只是一个构建模式而已,如果到处都是,你可以提交一个反模式  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-29 12:35 | 风雷云雪电
就C++来言,全局变量和单例是差不都,不过单例相对于全局变量来说,程序员不容易出错,程序员有可能重新实例化一个类而不是使用全局变量。
在其他语言中如Java,C#,单例是非常有必要的  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-29 13:07 | 溪流
@风雷云雪电
就C++而言,如果是不得不用的全局数据,那么它应该早早的就被规定好了的,而且只要做到不跨文件使用,出错的几率并不大。如果只能有一个实例,那么这个class可以静态化。如果不许实例化,可以private掉ctor。

对于java,C#,单例又体现在哪里?C#已经支持了 static class 的写法了  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-29 13:12 | 溪流
@x
因为我看到挺多地方都说单例模式如何如何了得,但是想不通,所以有此感慨。
  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-29 13:13 | 溪流
@陈梓瀚(vczh)
例子看懂了。但我看不太明白你的观点,呵呵  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-29 13:37 | Kevin Lynx
@溪流
这个问题某种角度来看,就如同对成员变量不管应用情景如何都提供Get/Set一样,同public一样了。

我觉得唯一的区别,还是一种安全控制吧:
class Singleton
{
public:
static Singleton &GetInstance() { static Singleton ob; .... }
private:
Singleton() { ... }
Singleton( const Singleton & ) ...
};
那么,这个Singleton对象就只存在一份。

当然,也有单件不作constructor的private限制的。
  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-29 13:55 | qiaojie
单件模式确实是一个错误。但是不应该用全局变量代替单件,而是应该用一组全局函数带代替单件模式,就像系统API那样。  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-29 13:59 | 溪流
@qiaojie
一组全局函数如果一定要完全OOP则可以封装到“静态类”里面:
class AAA
{
public:
static void foo();
static void bar();
//...

private:
AAA();
};  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-29 14:10 | 溪流
@Kevin Lynx
我觉得你这个例子并不说明什么
这个例子就是通常的单件模式的使用情形。

1、它没有避免全局变量的弊端。对结构不太注意的人随时可以Singleton::GetInstance();

2、如果它要单一实例,那么这里肯定有一个内在因素。一个比较通常的情况是,这个类是一个框架(或某个框架的一部分)。既然它是框架,那么框架本身自然可以将其隐藏,或者以本框架最头条使用说明的方式明令禁止实例化。如MFC的CWinApp,如果有人实例化2个CWinApp导致错误,一定是那个人太小白了而不是MFC太傻;类似的可能还有NTService的封装。除此之外可能还有些啥原因我一时罗列不出来。

3、如果它要被多个局部共享,那么这实际上就是赤果果的全局变量,用了就用了,没必要假装没用过


至于get和set,我现在还不知道自己感觉到底如何。至少我认为不是所有的都需要public出来的。最多,给所有非隐藏变量个get,给所有非只读公开变量来个set就差不多了吧。

  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-29 14:26 | yrj
@溪流
一组全局函数如果一定要完全OOP则可以封装到“静态类”里面:

静态类没必要
namespace AAA
{
void foo();
void bar();

//...

} // namespace AAA  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-29 14:32 | 溪流
@yrj

我是说,如果要满足形式上的OOP  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-29 14:58 | 远古毛利人
我觉得单件模式给库作者使用比较好,因为静态数据没法避免用户多次定义。
单件的话因为长得显眼,用户一看就知道。
另外,在GetInstance()里也可以做一些复杂的初始化动作,呵呵。  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-29 15:03 | gbb21
鉴于溪流GG的blog上了我的google reader,于是特来YM  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要?[未登录] 2010-03-29 15:16 | chentan
用C的思维去思考,就没有那么多思想负担了  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-29 15:45 | 矩阵操作
@远古毛利人
同意你这个看法。C++里面单件形式意义大于实际意义。  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-29 15:47 | 空明流转
@溪流
设计模式的目标在两个方面:
一个方面是给你一点你需要的自由,第二个是不给你除了给你的自由以外的东西。

某种意义上,Singleton是最好的用例。至于Singleton的实现,有很多种。
VCZH提供的,也是一种实现。

我看了一下楼上的评论,似乎都狭隘的将Singleton局限在Class::Instance()这样的GOF标准里面了。
但是实际上不尽然。特别是横跨Binary的,或者是C-Compatible的设计,都一定是GetXXX()这样一个自由函数的实现。

所以讨论Singleton模式,并不只是讨论实现,更重要的,是讨论两点,也就是我最初提到的两点:

第一,一个类型实例数量的限制;
第二,访问感知性(比方说如果我是GetInstance的时候,我每次访问都可以明明白白的追踪到访问点。而Global就比较困难,有时候你很难知道变量在什么时候被修改了。)  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-29 16:33 | 溪流
@空明流转
前面的论述我基本上接受,但最后两点还是想不通

比如第二点,我要知道他什么时候被修改了,如果用的是全局变量,我可能要全工程搜索变量名字,如果是单件模式,我可能要全工程搜索XXX::GeInstance(),这一点我看不出单件模式带来的任何好处  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-29 16:34 | OwnWaterloo
@空明流转
>>都一定是GetXXX()这样一个自由函数的实现

这没错。 而且还要区分2种语意:
1.
xxx_init
...
xxx_get

2.
xxx_get_and_init
第2种语意我不喜欢。


将xxx_get, xxx_init搞成xxx::instance完全是脱了裤子放屁。
本身就是一个free function的事情, 非要搞出个class出来。  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要?[未登录] 2010-03-29 16:51 | 清风
@溪流
遇到这种情况,难道你不是在GetInstance函数里检测被修改的时机吗.....?  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-29 17:23 | 唐荣军
你已经进步了,等哪次你觉得它还是有必要的时候,就表明你更进一步了。祝好运!  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-29 17:26 | 空明流转
@溪流
断点,谢谢。  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-29 19:53 | 陈梓瀚(vczh)
@OwnWaterloo
1:坚持所有singleton都必须在main之前自动初始化完成
2:坚持singleton之间不能有任何使用关系
3:因此不需要XX_init,get就好了  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-29 20:05 | OwnWaterloo
@陈梓瀚(vczh)
main之前自动初始化也是需要代码的。

C++的运行库会帮忙做这个事情。而C不行。 至少标准C不行。
编译器提供的DllMain或者 __atrribute__(constructor)啥啥的不算。

所以, C里面init是需要的。
  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-29 22:10 | 空明流转
@陈梓瀚(vczh)
这种坚持通常都颇具难度。。。  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要?[未登录] 2010-03-30 09:28 | hh
不去老老实实坐点业务 讨论这个有1毛的意义吗?

  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-30 09:53 | Iloveprogram
@陈梓瀚(vczh)
刚学singleton的时候,也是为那些个多线程不安全的问题烦恼过。后来一想何必那么麻烦,在使用以前实例化好就得了,使用的时候直接get。这样性能又好,又简洁。
看到大师也有这种观点,很是欣慰,呵呵。

btw,对你现在在做的东西很感兴趣,不过我自己水平未到。

  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-30 09:59 | 溪流
@hh
你如果觉得没意义,大可不必来此浪费时间,谢谢!  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-30 10:01 | 溪流
@唐荣军
我喜欢你的这种口气,但希望知道你的具体内容,不然这样的话我也会说  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-30 10:01 | 溪流
@空明流转
好的!这算单件模式一个优点吧。。  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-30 10:25 | holyfire
单件可以在设计时就考虑到自己是唯一的实例,但是用全局对象有几个问题,

1:对象可能产生多个实例,如果你的类隐藏的数据成员可能被构造函数修改的话,提供者就会失去控制权。比如一个不小心使用了值参数导致临时对象被构造。

2:如果有代码在main前面执行的话有初始化顺序问题

3:如果这个单件是个基类指针,单件可以在运行时配置并保证多线程安全

4:如果这个单件在DLL中并会被重新加载,单件模式更方便使用

5:单件模式和全局变量相比较只是书写习惯的问题

那么,如果你的要求很简单并没有涉及到以上问题(可能还有一些问题我没发现),那么全局变量的确可以满足你的要求。

很多人都觉得main之前初始化单件很容易,那是你工作的内容面还不够广,很多方面会导致你的代码在main前面执行而且是你不知道的情况下,比如DLL的静态链接库方式使用,使用第3方库,比如ACE会修改main宏替换自己的main函数,或者你的代码本身就在DLL中。  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-30 11:20 | 空明流转
@holyfire
Ace在工程上,就是一坨屎。。。完全没法用。  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-30 15:52 | 陈梓瀚(vczh)
@OwnWaterloo
不管要不要代码初始化,只要你坚持所有不同的singleton对象都不需要依赖于其他singleton对象来创建那么就没有问题。如果不行,那么证明设计有错,或者没错但是很难实现,或者没错很容易实现但是很容易写出bug,总之要改。  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-30 15:53 | 陈梓瀚(vczh)
@hh
你要是能把你做的业务写到博客,看公司开不开你啦  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-30 15:53 | 陈梓瀚(vczh)
@空明流转
控制大工程需要使用一些可能会造成开发起来有一点点麻烦,但是从根本上排除了很多bug的根源的方法。  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-30 15:55 | 陈梓瀚(vczh)
@OwnWaterloo
用一种语言去表达一些概念,如果造成不可消除的重复代码或模式的话,那么应该在可能的情况下更换语言。举个例子,你为PC开发软件,那么C完全没必要,C++能兼容它。因此你可以引入一点点C++的特征去消除你的困难,剩下的你爱用C写就用C写。  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-30 15:55 | 陈梓瀚(vczh)
@Iloveprogram
要以发展的眼光看问题。  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-30 15:56 | 陈梓瀚(vczh)
@OwnWaterloo
话说回来,只要保持singleton必须在main前构造完毕这个原则的话,就算你singleton的创建互相依赖,也是不需要锁的。  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-30 15:58 | 陈梓瀚(vczh)
@holyfire
那证明你把不该singleton的东西给singleton了,应该修改设计,而不是想办法实现singleton。

举个简单的例子,我可能需要在很多地方使用相同的正则表达式,那么每次都写regex(L"....") r;显然是浪费了构造时间的,所以这可能就会被放在一个全局的地方。那你说应不应该做成singleton呢?显然是不需要的,你需要的是把你这些regex放在一个Context类里面,在main函数创建,然后传递给所有其他对象。

还有,一个类是否应该成为singleton,不是类自己决定的,而是使用类的那个人决定的。  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-30 16:05 | OwnWaterloo
@陈梓瀚(vczh)
>>用一种语言去表达一些概念,如果造成不可消除的重复代码或模式的话,那么应该在可能的情况下更换语言。

只所以要说C:
1. 上面提到了C
2. C++做二进制兼容的东西很烦

而且, 如果不了解C++在初始化静态对象时做了哪些工作, 就会犯错。
比如, 很多人都觉得C++静态对象初始化是线程安全的, 其实是和实现相关的。
  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-30 16:12 | OwnWaterloo
@陈梓瀚(vczh)
>>不管要不要代码初始化,只要你坚持所有不同的singleton对象都不需要依赖于其他singleton对象来创建那么就没有问题。如果不行,那么证明设计有错,或者没错但是很难实现,或者没错很容易实现但是很容易写出bug,总之要改。

你说得也太武断了。 设计有问题?
总有东西的初始化需要申请内存, 能不依赖C heap和C++ free store?

初始化后有部分东西又需要向atexit注册, 又依赖另一个全局的东西。
初始化失败, 有部分人喜欢写log(虽然我不喜欢), 再次依赖全局的东西。
  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-30 16:14 | OwnWaterloo
@陈梓瀚(vczh)
>>话说回来,只要保持singleton必须在main前构造完毕这个原则的话,就算你singleton的创建互相依赖,也是不需要锁的。

class evil
{
evil()
{
pthread_create(... );
_beginthreadex( ... );
}
};

如果这个例子确实太邪恶, 别忘了还有可能会碰见进程共享数据。
  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-30 17:57 | holyfire
@陈梓瀚(vczh)
虽然看不明白你想对我表达什么,或者是找错人了?不过感觉你有点想当然了,好像人人都该像你规定的那样去做,不过我遇到的问题大多是是工作上实际遇到事,而你说的那个例子更像是用原型模式(Prototype)的情况,当然不应该作为单件模式,而且我并没有举例子说什么什么情况下该用单件模式,而是说遇到某种情况用单件模式比全局对象好,麻烦你看仔细点。  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-30 18:50 | 溪流
到后面我都看不大懂了~~~
搬张凳子学习了,各位大侠请继续~  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-30 22:25 | 陈梓瀚(vczh)
@OwnWaterloo
1:初始化的时候连内存都申请不了应该直接崩溃,这是最好的办法。所以这个不是理由。

2:main函数执行之前没有其他线程,不存在共享的读取问题。如果需要启动线程,应该让singleton提供函数让main函数执行并启动。任何库不应该悄悄启动线程,除了GUI。再者,你应该充分信任平台API,这是唯一你不可控制的东西。

3:singleton初始化的时候不相互依赖是一件好事,如果实在非依赖不可,那么一方面说明你可能将不应该singleton得给singleton了,另一方面则有可能是你把本来应该存在同一个singleton得给拆分成多个singleton了,种种设计问题带来的非依赖不可的结果。

4:如果一个二进制发行的库是你开发的话,那么不再库里面提供singleton是一个很好的选择。一个程序的所有singleton只能存在在exe里面。话说回来,二进制其实不是问题,你应该坚持你自己的程序和库都是用同一个编译器编译。如果库没提供二进制,那么应该索取代码,是在索取不了,那么使用其他库。作为一个库的发行者,要么提供C++代码,要么提供所有流行编译器的二进制编译结果。这才是负责任的,除非你从一开始就不打算跨编译器或者跨平台(windows和linux都有主流C++编译器)。  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-30 22:31 | 陈梓瀚(vczh)
@OwnWaterloo
然后我再次强调,一个类是否应该当成singleton,应该取决于调用者而不是类自己,除非因为平台的API限制(譬如说windows下面的GUI通常都会有的Application类)  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-30 22:37 | OwnWaterloo
@陈梓瀚(vczh)
>>初始化的时候连内存都申请不了应该直接崩溃,这是最好的办法。所以这个不是理由。

"申请不了"同"需要依赖内存分配器已初始化" 完全是两码事。
你又跑题了。

>>任何库不应该悄悄启动线程,除了GUI

这只是"你觉得"应该这样。
但你马上又说了一个反例。

3. 我只想说对全局某些服务的依赖是很难避免的。
singleton关我什么事? 我老早不用这种脱了裤子放屁的玩意了。


>>作为一个库的发行者,要么提供C++代码,要么提供所有流行编译器的二进制编译结果。这才是负责任的。

作为一个二进制库的发布者, 将库用C实现并提供C++的header-only的绑定层; 或者发布C++的源代码。
这才是负责任的。

所有流行编译器? 你知道什么叫所有流行编译器么?
编译器种类×编译器版本×编译器运行库版本×你的库版本

你觉得你能负这个责, 你就继续玩吧。
  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要?[未登录] 2010-03-31 10:42 | sun
我想还是比较有用的,举个例子,也是我做过的,创建一个singleton类,需要常链接到服务器,时序同步,在不同的线程间共享,非常的高效,尤其是在资源很缺乏的机器上,像iphone设备,碰到了就觉得需要了.......
其实平时很少用!  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-31 15:40 | 陈梓瀚(vczh)
@OwnWaterloo
显然“所有流行编译器版本”是一个你只需要下载完写了从vcproj到的makefile生成器以后就自动完成的事情,一劳永逸也,想做当然能做,而且随时更新。运行库版本一律使用static链接,因此可以跟你的编译器版本捆绑在一起。而且,编译器的【小版本】之间的变化导致lib不能通行应该归咎于编译器的质量,而不是你。

第二,反例当然是要的,有些东西必须成为singleton,典型的GUI就是,一个程序不可能也不应该同时使用N套平行的GUI库(嵌套关系除外)。所以这个没有任何问题。

第三,main之前的任何异常都不要捕捉,任由崩溃。想log就捕捉了log,log完还是要throw;以便崩溃

第四,二进制发布者那一句我们两个说法没有任何区别

第五,VC++里面没有看见任何singleton在创建前new还不能用的,如果其他编译器有,那是编译器的bug,要么放弃它,要么放弃singleton。

第六,我的所有观点都从以下方面出发
1:尽可能将bug扼杀在摇篮里
2:制作出来的程序容易被更改  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-03-31 15:57 | OwnWaterloo
@陈梓瀚(vczh)
>>显然“所有流行编译器版本”是一个你只需要下载完写了从vcproj到的makefile生成器以后就自动完成的事情,一劳永逸也,想做当然能做,而且随时更新。

这只是构建脚本而已。 我说的是不同编译器产生出的二进制代码的兼容性。
你能用msvc链接到一个mingw生成的二进制库吗?
你能用msvc链接到前一个crt版本吗?

>>运行库版本一律使用static链接,因此可以跟你的编译器版本捆绑在一起。
看吧, 你又"一律", "一定" 什么的了。

这是C++语言本身的问题。 C++的特性太复杂, 而且是一门开放的语言, 所以会有很多二进制上不兼容的特性。
而且C++这门语言本身就会促使开发者使用复杂的设计。

>> 一个程序不可能也不应该同时使用N套平行的GUI库(嵌套关系除外)
你没见过而已。 确实有这样的东西存在。 MFC+WTL+还有一个什么忘记了。
当然, 那东西确实丑陋。
不过已经是这样子了, 推倒重来的代价公司受不起, 用户也受不起。


>>main之前的任何异常都不要捕捉,任由崩溃。想log就捕捉了log,log完还是要throw;以便崩溃
再次强调, "需要全局的依赖" 和 "处理全局初始化错误" 是两回事。
  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-04-01 01:46 | 沙城来客
1.做个标识,让人家知道这个东西是单例的 明白该怎么用 全局就没有这种作用,不过到底怎么用是调用者的问题,不过至少自己的份内事情要做好
2.推迟初始化 在大系统里面一开始一堆全局的大类进行初始化是很恐怖的事情  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-04-01 15:50 | 陈梓瀚(vczh)
@OwnWaterloo
如果你搞定了构建脚本,你怎么还会有vc连接不了mingw的lib的问题呢?已经被生成的一大堆lib搞定了,你挑一个正确的就好了。

“C++促使程序猿使用复杂的设计”这个东西跟论点没有任何关系,既然要写库,那么肯定会有些约束的。一律和一定跟这个没有任何冲突。根据第一个观点,第一,构建脚本好写。第二,有了足够的构建脚本你就可以挑选任意种类的lib。第三,因此编译器相同,因此可以static。因为这是运行库,运行库跟程序里面的功能模块是两回事,尺寸特别小,static没有任何坏处,没有static你还有机会犯错。

我们并不需要照顾100%的人的需求,譬如少数公司因为历史原因造成的N个GUI一起使用等等(其实历史原因跟singleton的主题并没有什么大的关系)

最后,我不认为全局初始化错误除了log以外应该做其他事情。如果连初始化都没搞定,那么显然应该崩溃。如果不应该崩溃,那么那个东西就不属于初始化的一部分,而应该类似于“插件”,这种时候不能用singleton,而应该用一个manager来管理这些事情。当然manager需不需要singleton是另外一回事请,总之是在main之后才开始做的。  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-04-01 16:57 | OwnWaterloo
@陈梓瀚(vczh)
>> 一大堆lib搞定了,你挑一个正确的就好了。
挑得出来吗?

你会为VC6用户生成相应的binary吗?

客户使用了-fabi-version 怎么办?
客户使用了-mno-align-double又怎么办?

你要规定用户所使用的编译参数? 你能规定用户使用的编译参数?
你能确保用户"仅仅使用你一个人的库"?

你想得太简单了。

>> 那么肯定会有些约束的
这些约束会被很不经意的打破。 很难控制住。
因为C++给了程序员太多可以玩, 可以炫的东西。
所谓的"心智包袱"。

>>尺寸特别小,static没有任何坏处
算了, 你总是把很有争议的话说得如此绝对, 我还能说你什么呢。


而且我第3次强调了, 我不想讨论全局初始化失败应该怎样。
你觉得应该怎样你可以继续说。

我上面举的例子, 仅仅是为了说明对"全局的依赖很难避免"。
我觉得已经足够说明了。
  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-04-02 12:25 | cexer
把单件放在其它模式堆里,确实有点鸡立鹤群的感觉,它并没有其它模式那样有启发性,所有写程序的人都知道世上有全局变量这个东西,那何必要取个好听的名字像模像样地研究一番呢,《设计模式》的伟大除了让人学会到很多手法,还有一点就是统一了很多概念,并为之提供了许多标准的名词方便大家研究,综上所述,我觉得“单件”就是一个虚名,你喜欢叫它“全局变量”也行,大家心里的概念没有差别,只是未必真是用全局变量来实现而已,所以不用在一个名字上纠结。

谁不想用赤祼祼的全局指针,它们原始又纯朴,天然无雕饰。可是真的要用它们来实现一份库级别的代码,就好像双手抛飞刀一样危险,不仅抛的人要两眼圆睁神经紧绷,连观众都要跟着捏一把冷汗。全局变量本来没有错,错的是在它们之上作出的许多美好的假设,假设谁一定在谁之前产生,谁一定在谁之后销毁,谁依赖着谁,谁又被谁依赖着,谁是线程安全的,谁又一定不会被多线程访问。互相完全没有依赖关系,不用额外控制,像终结者一样智能,完成任务又知道自己终结的全局变量,只是个传说。

有很多以单件名字的手法,Meyers 单件,Alexandrescu 单件,Phoenix 单件,Schwarz 计数器,你看它们好多都叫做“单件”,但是你喜欢叫 Meyers 全局对象,Alexandrescu 全局对象,Phoenix 全局对象 也可以。

我个人觉得,把“全局变量”拿来和“单件”相提并论是很不妥的事件。就好像拿“汽车”和“交通工具”比一样。不是一个层面上的东西,单件也许是全局变量,也可以不是,“全局”也有多种理解角度,存储位置(堆上,栈上,静态数据区),生存区域(线程局部,进程局部,模块内部),生存周期(何时生,何时死,不死)。只是“全局变量”已经不能说明它的复杂度,但是一提“单件”大家都明白将要说的是什么,这就是“单件”存在的价值,这也是《设计模式》一书提出“单件模式”伟大所在。  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-04-02 15:54 | OwnWaterloo
@cexer
用于单件的那些技术, 同样可以用于全局数据初始化。

C运行库为你初始化堆分配器, 不也不需要你多余控制?
进程终结后也会自己终结。
呃, C库不一定会真正释放, 有可能留给OS。
那换个例子, atexit。

所以单件根本不是什么伟大的发明。
只是OO时代的顺应产物。
  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-04-03 01:22 | cexer
@OwnWaterloo
我说的可能不大清楚,我的意思是“单件模式”只是一种概念,正是类似“全局数据”这种东西的一种抽象形容,不然何以称“模式”。拿“单件模式”和“全局数据”本身比,是没有可比性的,一为抽象,一个具体,一为模式,一为实例。它跟OO也没有关系,一个C全局裸指针,也是一份单件的实体。所以不要再比来比去的了。

  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-04-03 19:51 | OwnWaterloo
@cexer
在我看来恰恰相反, 全局数据与用户之间的交互形式有若干, 而单件只是其中一种。
  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-04-04 09:53 | hello
全局变量可以实现单件模式的功能,但是单件模式可以避免生成多个该类型的对象
  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-04-10 13:21 | 蚂蚁终结者
还是要看实际情况,并不是任何时候都可以用全局变量替代单例的。
如在Symbian C++ S60V3以前,是不允许WSD数据(全局变量)存在的,这种情况下必须用Tls Singleton这样的模式。。。  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2010-04-10 15:08 | tangxinfa
单件模式较之全局变量(对象)的一些优点:
1,防止用户构造出另一个对象,这也就是为什么称之为单件。
将构造函数、拷贝构造函数私有化,而只能通过getInstance()接口获得唯一的实例。
2,延迟创建对象。
只有用到的时候才会创建对象,防止程序启动时间过长,不做无用功。
3,全局变量就够用了,但感觉以后会需要之前两点特性。
4,全局变量命名上抓狂了:g_xxxxxxxx,globalXXXXXXXX,想来想去还不如:CXXXXXXXXXX::getInstance()够直白。
5,调试时好设断点。  回复  更多评论
  
# re: 讨论:单件模式的优点何在?有无存在的必要? 2015-05-22 16:35 | lurenjia
@陈梓瀚(vczh)
轮子哥。。  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理