游戏开发论坛

 找回密码
 立即注册
搜索
查看: 4053|回复: 6

关于单件

[复制链接]

38

主题

96

帖子

148

积分

注册会员

Rank: 2

积分
148
发表于 2005-12-31 10:31:00 | 显示全部楼层 |阅读模式
[em21]
有时和朋友谈起单件,有很多朋友对这个的理解不是很透彻,再次谈谈我对单件的理解,以及一些可能是错误思考方向或实践中的错误

有朋友把形如下的方法叫做单件。

class Singleton
{
     static Singleton * instance() { return &ms_singleton; }
private:
     static Singleton ms_singleton;
}

Singleton Singleton::ms_singleton;

其实我们对单件的理解是很重要的,正因为上面的代码也可以叫做单件,但如果象上面的实现方法,我真不知道为什么我不直接定义一个全局变量,为什么要搞个麻烦的代码写成上面的样子,把一个简单的全局变量应用麻烦化呢?

对单件我的理解很直接:一个大家都可使用的设备,装置,机构,功能组。最最重要的就是一个标准通用设备。随时可以使用,就是随时可以使用,如果有人要求使用这个设备,这个设备就会为请求者提供服务。

如果和我的理解一致,那么就应当考虑如何正确的满足提供这个设备的方方面面的问题。

1.单件 不等于 静态数据+静态函数
2.访问点必须是唯一点。
3.设备释放必须是所有使用者都不再使用这个设备才可以释放。
4.多模块(动态链接库)之间的单间提供方法
5.多线程支持问题

以上问题说明,要想提供一个单件,并不是什么代码模式所决定的,是一个设计问题。
具体的代码并不能说明你是一个满足要求的单件。单件不仅仅是代码,任何代码设计与模式设计要分开理解,他不是同一件事情,功能模式设计是指引代码编写需求,而代码设计为满足需求而做的代码编写设计。

首先,在实现一个代码设计的时候,对需求的理解远远大于代码本身的编写的作用。

从上面的需求来看,其实单件本身的意义我并没有体会到,甚至我不同意单件的使用方法放在我们的程序设计当中,原因有几个:

1.我应当明确知道我是不是要调用一个功能,如果需要调用,我最好在事先创建好。这样我可以在开始提供这个服务时就能够处理服务提供是否成功。
2.我实在是不需要这样一个设备必须是动态创建的一个全局设备,并且在我使用过程中又不能销毁的东西,他的系统内存说占用了,又有时不会占用,把我的程序内存布局打乱。
3.我最重要的需求其实是,一个全局变量,有唯一访问点的唯一实例的一个功能对象。并且完全是概念上理解的,并没有静态数据和静态函数的需求。
4.为了有效地控制单件的使用作用域,要为她加入使用域控制功能,最后我不得不把他理解为COM组件的使用方法,是一个唯一实例的COM组件功能。并且每一个COM组件的根组件都是这个样子的,对应唯一的GUID,并且在系统中,只会创建一次。

36

主题

1047

帖子

1147

积分

金牌会员

Rank: 6Rank: 6

积分
1147
发表于 2005-12-31 12:03:00 | 显示全部楼层

Re:关于单件

1.你没有完全singleton模式的含义,模式不是为了模式而模式的,是有了需求才实作出来的。
2.你可能自己写程序写惯了,没有团队协作的经验,当别人使用你的程序库的某个类只想有一个实例但又无法去限制其他人创建多个对象时,这时你会明白singleton模式。建议再好好读一下设计模式。
3.多线程、内存分布等问题只是singleton模式在实际平台上的应用问题,并不是singlleton的核心,不要以偏概全。
4.你对COM的理解也不正确,GUID并不是为了只创建一个对象的目的而存在,而是COM类型的唯一标识,在一个应用中可以创建多个COM组件是大家都知道的常识。
5.不明白你指的单间使用作用域是什么概念。
6.静态函数和成员只是c++语言实现singleton的一种方式,singleton模式没有规定实现方式。

38

主题

96

帖子

148

积分

注册会员

Rank: 2

积分
148
 楼主| 发表于 2005-12-31 15:30:00 | 显示全部楼层

Re: 关于单件

我不想和你否定式的谈论问题,
1.你没有完全singleton模式的含义,模式不是为了模式而模式的,是有了需求才实作出来的。
关于你的这句话,如果你说我没有理解他,那么请说出对他的正确的理解,比你说这个不对时更有价值的。

2.你可能自己写程序写惯了,没有团队协作的经验,当别人使用你的程序库的某个类只想有一个实例但又无法去限制其他人创建多个对象时,这时你会明白singleton模式。建议再好好读一下设计模式。
这一点首先你得判断方法我不知道从何而来,小生8年的程序编写,5年的合作开发实践也许算不了什么,但总会有些事情让我碰到,还有,我从哪里已没有反对过singleton的用意,你从何判断我在否定这个模式?如果谈得是我对他的不了解,请说出你的理解,我想更有价值。

3.多线程、内存分布等问题只是singleton模式在实际平台上的应用问题,并不是singlleton的核心,不要以偏概全。
对于这个来说,我的意思是为了解释说单件的提供方法和应用范围是受到
特定情况限制的,如果不在设计的时候知道这些事,你提供给别人的单件及其容易造成使用者的疑惑,会有,为什么这个在我的多线程下出了严重的当机问题? 我对这方面只有一个根据实际需求小心设计这些东西,你有更好的办法吗?如果有,请讨论具体方法。

4.你对COM的理解也不正确,GUID并不是为了只创建一个对象的目的而存在,而是COM类型的唯一标识,在一个应用中可以创建多个COM组件是大家都知道的常识。
关于这个请谨慎读我所写的文字内容,我只是说利用这些东西,遵循COM
的设计假想环境,非常孤立的提供一个松耦合的的单件,要是我的措辞有问题,但是,我怎么也觉察不出来我说的话是你理解的那样。


5.不明白你指的单间使用作用域是什么概念。
在一段程序当中,几乎很多人认为单件作用域是全局,但事实却不是那样,无论你提供了什么样的一个单件,除非你要求单件中不会引用到其他
单件,但实际问题中,就有些单件是几个单件互相引用,非常容易出现循环引用,这样,同是单件,在释放空间时如果再次被引用了怎么办呢?
是重新创建? 还是置之不理?

6.静态函数和成员只是c++语言实现singleton的一种方式,singleton模式没有规定实现方式。
这里所说的意图是这种方式根本就不如一个全局函数更直接,根本就是为了说明不要认为 静态成员数据+静态成员函数 就是单件,这种方法实际上很没有用处,这是我的疑点,目前认为这种写法完全不如写成
全局变量+全局函数(获得唯一处理)
因为我看到很多代码中写了这样的东西,有时候这些“单件” 还会出现返回了无效的指针,造成了当机,并且有些代码中还写了检测单件是否存在
并且每一个用到单件的地方都进行了错误指针检查。
因此对于这些用法和使用方法表示怀疑?

如果你能够提出 哪里不用 单件 是不能够完成任务的地方提出来,这将对我有很大帮助。 否则会加速我抛弃这个东西的速度。

193

主题

870

帖子

903

积分

高级会员

Rank: 4

积分
903
QQ
发表于 2006-1-2 17:57:00 | 显示全部楼层

Re:关于单件

我是比较赞同二楼的说法的, 楼主太过于理论化了,其实单件只不过是一种设计模式,并不是特定的实现方法,对于不同的程序来说,对单件的实现要求也不一样,多线程或者说堆分配以及控制构造和释放时间都是依照具体项目的需求来实现的。更高的通用性是以性能来换取的,我们所作的事就是在性能和通用性中找到一个平衡点。
但是其实像楼主这样执著的找到通用的模式代码的人还有更出名和厉害的,那个人就是loki库的设计师,他一直致力于用魔板来实现不同的设计模式,关键是模版本身并不损失运行时效率,他在这方面已经作了相当多的工作,也成功地实现了一些模式的模板化,但是和楼主一样,他也是仍然受到很多人的质疑,毕竟很多设计模式是需要和具体的工程来结合的。
对于单件模式我推荐楼主看看游戏编程精粹1中的实现,他具体的讲了几个不同的实现方法,而且伟大的Ogre图形引擎的单件模式就是使用的这个,高效并很强通用性,量又足,我们一直用他。

对于“认为这种(单件)写法完全不如写成全局变量+全局函数(获得唯一处理)”

我是不赞同楼主的,这种实现方法可能在现在的项目中可能就是一个全局变量,但是对象封装实现单件接口,至少要灵活规范很多,比如如果忽然客户改变主意说说要加入多线程,我们可以在不改变接口的情况下实现新的策略,这也就是设计模式的好处。如果只是使用一个全局变量,可能需要对整个软件东大手术。联想到面向对象一些比较奇怪的要求,就是说对于成员变量一定要用set 和get来处理 ,而不能直接使用,大体也是这个道理吧~。


“如果你能够提出 哪里不用 单件 是不能够完成任务的地方提出来,这将对我有很大帮助。 否则会加速我抛弃这个东西的速度。”
虽然这句话不是问我的,但是还是任性的想要说点东东,其实似乎在面向过程的语言中是没有设计模式的(当然你硬要用C实现oop我也没办法),但却能实现现在设计模式所有的功能,所以可能说任何设计模式都不是“必须存在”的,再换个角度,在汇编中,可能就只有赋值,跳转,运算,压栈出栈,寄存器操作等等几十条指令,但是我相信可以实现任何函数阿,对象阿,宏阿,模板阿,所有你高级语言能实现的功能。这样也就是说,函数什么的也不是必须要用的了。对阿,对于机器码只试用0和1就好了,我们之所以使用千奇百怪的复杂的高级语言就是因为要照顾我们这些愚蠢的人脑,让我们工作简单一些,所以虽然单件不是必需的,但是确实是一个不错的东西,不是么。

顺便提一句:小生今年刚毕业,从来没有合作开发实践经验,我也不知道我能算得上什么 [em1]

38

主题

96

帖子

148

积分

注册会员

Rank: 2

积分
148
 楼主| 发表于 2006-1-2 21:39:00 | 显示全部楼层

Re:关于单件

嗯嗯嗯,大家踊跃发言,欢迎欢迎。这就是交流。

我同意楼上的某些看法,但大家都有局限性,一个模式大多数承认为不限制实现细节,具体问题看具体的环境要求去实现,对于我所提到的问题就是想说明某种具体实现方法并不是关键,但目前对程序实现的理解,我是更多的思路放在一个真正可重用角度来考虑的,但是上面的一个具体实现,显然不适合我目前所要达成的最终重用要求,上面的具体实现,限定了很多,所以说,那个重用范围非常小,哪怕是用到另一个线程,另一个程序,另一个DLL都是非常不适合的,那么,假设有一种方式能够提供给你真正意义上的组件化的实现方法,为什么我不把精力用在实现这个具体 “实物”式的一个设备呢?
Windows中的 Clipboard 是一个非常实用的物品,可以在任何程序之间使用,他的代码我想是基本不用在你的任何客户程序中修改和适应,这是一种应用,它具体是什么我并不是很在意,但对于这种设计概念非常推崇,一步一步把这些功能精炼化,才是有效减少程序制作发展之道
否则,程序员将在无穷无尽的重复劳动中度过余生。
目前有一个非常有意思的现象,目前引入C++或某种OO语言的项目,程序员变成了无数不用动脑的写代码劳动,而且更多的人加入这个行列,并且动不动就是几十万行代码重新COPY,改进写到一个新项目中。我体会不到这种每次都要做适应性重写的工作有什么好处。

似乎有跑题了,不过我就是爱说一点,而且乱说,特别赞赏2楼兄弟直言,就此我所表达的是单件这种模式的实在用途是什么,另外对楼上的朋友说一声,如果一个没有实在用途的再聪明的方法也不值得去推崇,这是我的观点,我不想陷入C和C++哪个好处更多的怪圈,如果C可以很好的,非常得体的应用于软件设计,为什么要用所谓单件的模式呢?

直到现在,我还是一个比较重要的问题没有得到解答,那就是单件的必要性和实在必然性用途是什么,既然他提供的是一组功能,为什么不给出一个合适的功能组?

193

主题

870

帖子

903

积分

高级会员

Rank: 4

积分
903
QQ
发表于 2006-1-3 16:33:00 | 显示全部楼层

Re:关于单件

关于后面的问题我还是拿不出教科书上的说法,因为设计模式和游戏编程精粹1都在单位,我个的理解是这样的,单件是确保一种类型支拥有唯一实例(附带的好处相对于全局变量是我们可以确定构造和解构顺序,确保在内存中的分配位置等等).其实你说如果我再写的时候注意一点也就不会有第二个实例了,当然C语言完全可以做到,从头到尾我们都没有必要引入c++的,或者最起码有些地方我们不必引入C++这等复杂而低效的东西。

为什么我们一定要用C++呢?

你可能只认为面向对象是一种工具,而不认为他是一种思想。

首先我想问一下,我们用计算机在做什么工作呢?
简单的说,我们再用计算机内部的数学去重构物理世界。
而数学的精妙之处,就在于到目前为止,似乎数学就是这个物理世界的完美抽象,目前还没有人能够解释为什么会是这样,但是早晚会解释的。
可能我说得太抽象了,举例子来说,现在数学家看的距离似乎比物理学家要远,数学家说那里会有一颗星星(推导),物理学家在之后却真的发现了这颗星星(归纳)。我们现在对于宇宙等领域的研究已经以数学为主,而物理似乎沦为对数学推导的验证手段。这正是因为数学是我们世界的完美模拟。

而现在的计算机模型却不是这样,其中有太多人为的演义,和我们的物理世界相差甚远。我们的计算机模型并不是对世界的重现,而只是某种外观上的模拟(我也糊涂了)。

我们公司的boss是OpenGL发明者之一,ATI前总裁,图形学先驱,基本上很多图形学的一些东西都是他发明的,反正是个牛人,只和我说过一次话,而且基本是骂我。
但是他提到,现在整个图形学的模型都是错误的,只有贴图是比较正确的,所以所有模型在将来都要从头建立,最终图形学的目的是让显示器里面的人物在你身边真实的移动。
至于为什么这么说,我得智商不够,你还是问他去吧。
我的理解是:比如我们所看到的现实世界是因为光线的存在,而在计算机世界里面因为硬件速度的关系,我们没办法实现光线跟踪。所以我门做的只是对世界某种程度的模拟,而不是重现这个世界。而当计算机硬件和设计思想进步到一定程度的时候,我们有机会实现对物理世界的重现。

跑了那么长的题,我想说的是在我看来面向对象是更接近对真实世界的重构(只是更接近,而不是完全的重构),比如说有一头猪,用汇编来说明的话可能是(这又一个舌头,吃饭时候会用,这又一个耳朵,听东西时候会用...<数据和操作都在寄存器里面进行>),用过程化语言说明的话可能是(它吃饭,它睡觉,他交配...<一堆函数>),用面向对象来说就是(这是猪这类型的一个对象<一个类的实例>)。

相对来说面向对象的思想更接近我们所生活的世界,不是么。随着计算机科学的进步完善,面向对象思想的重要性愈加凸显,最近你所知道最时髦的几种语言中,有几个是面向对象的呢?基本上都是吧,哦那个支持不完善的是PHP,那个只是基于对象的是javascript。lua和python不是很酷么都是动态的呢,静态的C#和java也不错了。其他的语言不也都是由面向对象的版本吗。你要是非说那老古董Ada什么的我就没辙了。

当然,我并没有说面向过程化语言和结构化语言消亡,就如同电视永远不能代替书和报纸一样,也不愿意争论C++是否比C好,离开实际的应用就如同哲学上争论孙子的功和墨子的守一样没有结果.

我只是说,面向对象,很酷,不是么,

object!why not?

===============================
附带说一句,我是个很不象话的人,很喜欢黑客精神,所以总是给自己安排喜欢什么不喜欢什么的阵营,我是反微软阵营,挺任天堂阵营,反对垄断阵营,支持linux阵营,丁磊很强阵营,盛大傻X阵营,C#不如java阵营,jsp不如php阵营,php万能阵营,xbox360日本买不出去真爽阵营,
软件工程、设计模式、面向对象特别好阵营。
你问我为什么说他好,这种事情就如同恋爱一样没有理由的,喜欢就是喜欢了。
但是因为现在做掌机,公司全都是c阵营,妈的天天被排挤 [em6]

===============================
设计模式的一个好处是 首先对相同功能的代码提供了统一的命名,类似微软的匈牙利命名法一样,不过更高一层,这样也便加大了代码的可读性。

3

主题

26

帖子

30

积分

注册会员

Rank: 2

积分
30
发表于 2006-7-15 10:55:00 | 显示全部楼层

Re:关于单件

5年团队经验的楼猪单件写错了!这样写哪里是单件,单件一个重要特点就是防止被外部事例化,单件模式如下:
class sSingleton

{

public:

       static Singleton* Instance();

protected:

       Singleton();

private:

       static Singleton* _instance;

};
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2026-1-24 23:07

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表