当前位置:  开发笔记 > 编程语言 > 正文

单身人士:好的设计还是拐杖?

如何解决《单身人士:好的设计还是拐杖?》经验,为你挑选了11个好方法。

单身人士是一个备受争议的设计模式,所以我对Stack Overflow社区对它们的看法感兴趣.

请提供您的意见的原因,而不仅仅是"单身人士是懒惰的程序员!"

这是一篇关于这个问题的相当不错的文章,虽然它反对使用Singletons: scientificninja.com:performant-singletons.

有没有人对他们有任何其他好文章?也许是为了支持单身人士?



1> Tyler..:

在保护单身人士方面:

它们没有全局变量那么糟糕,因为全局变量没有标准强制的初始化顺序,并且您可以轻松地看到由于天真或意外的依赖顺序而导致的不确定性错误.单身人士(假设他们在堆上被分配)是在所有全局变量之后创建的,并且在代码中的一个非常可预测的位置.

它们对资源惰性/缓存系统非常有用,例如慢速I/O设备的接口.如果您智能地为慢速设备构建单独的接口,并且没有人调用它,那么您将不会浪费任何时间.如果另一段代码从多个位置调用它,您的单例可以同时优化两者的缓存,并避免任何双重查找.您还可以轻松避免单例控制资源上的任何死锁条件.

反对单身人士:

在C++中,单身后没有很好的自动清理方法. 有一些解决方法和稍微有些方法可以做到这一点,但是没有简单,通用的方法来确保你的单例的析构函数总是被调用.对于这个目的而言,这并不是一个非常可怕的记忆 - 只是将其视为更多的全局变量.但是,如果您的单例分配其他资源(例如锁定某些文件)并且不释放它们,则可能会很糟糕.

我自己的意见:

我使用单身人士,但如果有合理的选择,请避开它​​们.到目前为止,这对我来说效果很好,而且我发现它们是可测试的,尽管测试的工作稍微多一些.


第一点的假设是一个很大的飞跃,通常堆分配不是如何创建单例(至少在C++中).
MadKeithV,我不确定.有一个标准模式,其中一个成员函数,比如MyClass*MyClass :: get_instance(),检查一个静态成员指针,如果它是NULL则调用new来分配(在堆上)共享实例.单身人士将如何生活在其他地方?
@Tyler:我刚刚看到下面的代码,它支持@MadKeithV不使用heap for singleton的视图.`class MySingleton {public:static MySingleton&getInstance(){static MySingleton instance; 返回实例; } private:MySingleton(); 〜MySingleton(); }; `.参考 - http://stackoverflow.com/questions/2593324/c-singleton-class

2> Brian..:

Google有一个针对Java 的Singleton Detector,我认为这个工具必须在Google生成的所有代码上运行.删除单身人士的简单原因:

因为它们可以使测试变得困难并且可以隐藏您的设计问题

有关更明确的解释,请参阅Google的" 为什么单身人士有争议 ".


谷歌还有一个会计部门; 这是否意味着每个开发者应该得到一个?禁止使用某些结构的决定是Google的一项商业决策,它更能说明其内部环境.毫无疑问,一些手动调整的机器代码仍然在那里被弄乱,但出于商业原因,不仅任何人应该这样做.

3> Orion Edward..:

单身人士只是一件奇装异服的全球变数.

全局变量有它们的用途,就像单身一样,但是如果你认为你正在用单例而不是使用一个令人讨厌的全局变量做一些很酷且有用的东西(每个人都知道全局变量是坏的mmkay),你不幸会被误导.



4> denis philli..:

Singleton的目的是确保一个类只有一个实例,并提供一个全局访问点.大多数时候,重点是单个实例点.想象一下,如果它被称为Globalton.这听起来不那么有吸引力,因为这强调了全局变量的(通常)负面含义.

大多数针对单身人士的好论据都与他们在测试中遇到的困难有关,因为为他们创造测试双打并不容易.


那么为什么一个类应该确保它只有一个实例呢?这几乎违背了面向对象编程的目的.
通常你只想要一个记录设施?或者你正在包装一些voodoo dll,你不想让它加载dll两次?
@Calyth但_why_将其作为自己的责任,当它显然是系统责任时.(对象的任何一个实例都可以正常工作,但如果不满足一个时间约束的唯一一个实例,系统可能会失败)

5> Bleadof..:

在Google测试博客中,MiškoHevery有三篇关于Singletons的好文章.

    单身人士是病态的骗子

    所有单身人士都去了哪里?

    单身人士的根本原因


我认为其中一个"解决方案"是依赖注入,它实际上为你处理了实例注入,它减轻了单例的反模式.:)看看Guice!http://code.google.com/p/google-guice/

6> Chap..:

单身人士不是一个可怕的模式,虽然它被滥用了很多.我认为这种误用是因为它是较简单的模式之一,并且单身人士的新手被全球副作用所吸引.

Erich Gamma曾说过,单身人士是他希望的模式,不包括在GOF书中,这是一个糟糕的设计.我倾向于不同意.

如果使用该模式以便在任何给定时间创建对象的单个实例,则正确使用该模式.如果使用单例以产生全局效果,则使用不正确.

缺点:

您在整个调用单例的代码中耦合到一个类

使用单元测试创​​建麻烦,因为很难用模拟对象替换实例

如果由于需要多个实例而需要稍后重构代码,那么将单例类传递给使用它的对象(使用接口)会更加痛苦

好处:

在任何给定的时间点表示一个类的实例.

根据设计,您正在执行此操作

在需要时创建实例

全球访问是一种副作用


"全球访问是一种副作用"我很高兴有人指出这一点.全球方面可能是单身人士中最被滥用的部分

7> Repo Man..:

小鸡挖我,因为我很少使用单身,当我这样做时,通常是不寻常的.不,说真的,我喜欢单身人士模式.你知道为什么?因为:

    我很懒.

    什么都不会出错.

当然,"专家"会抛出一堆关于"单元测试"和"依赖注入"的讨论,但这些都是野狗的肾脏.你说单身人士很难进行单元测试吗?没问题!只要宣布一切公开,就把你的班级变成一个充满全球善意的有趣之家.你还记得1990年代的Highlander节目吗?单身就是这样的,因为:A.它永远不会死; 和B.只能有一个.因此,请停止倾听所有那些DI weenies并放弃实施您的单身人士.以下是一些更好的理由......

每个人都这样做.

单身模式让你立于不败之地.

单身人士押韵与"胜利"(或"乐趣"取决于你的口音).



8> Cem Catikkas..:

我认为使用Singleton模式存在很大的误解.这里的大多数评论都将其称为访问全球数据的地方.我们需要在这里小心 - Singleton作为模式不是用于访问全局变量.

Singleton应该只用于给定类的一个实例.Pattern Repository有关于Singleton的很好的信息.



9> andreas buyk..:

我与之合作的一位同事非常单身.每当有某种东西像管理者或老板那样对象时,他就会把它变成单身,因为他认为应该只有一个老板.每次系统采用一些新的要求时,事实证明允许多个实例是完全正确的理由.

我会说如果域模型指示(而不是"建议")有一个单身,则应该使用单例.所有其他情况只是一个类的单个实例.



10> Dan Blair..:

我一直试图想出一种方法来解决这里可怜的辛格尔顿的拯救问题,但我必须承认这很难.我已经看到它们的合法用途很少,并且当前的驱动器进行依赖注入和单元测试它们很难使用.他们肯定是编程设计模式的"货物崇拜"表现我曾与许多程序员合作过,他们从未破解过"GoF"书,但他们知道'Singelton',因此他们知道'模式'.

我不得不与Orion不同意,但大多数时候我看到singeltons过度使用它不是服装中的全局变量,而更像是服装中的全球服务(方法).有趣的是,如果您尝试通过CLR接口以安全模式在SQL Server 2005中使用Singeltons,系统将标记代码.问题是你有可能运行的任何给定事务之外的持久数据,当然如果你使实例变量只读,你可以解决问题.

这个问题导致我一年的很多返工.


我从来不明白为什么人们如此喜欢这种模式.我想这是因为它'允许'你使用全局变量,这可以省去重新思考设计的麻烦.当然,除此之外,它没有.

11> Gishu..:

圣战!好吧,让我看看..上次我检查设计警察说..

单身人士很糟糕,因为他们阻碍了自动测试 - 无法为每个测试案例重新创建实例.相反,逻辑应该在类(A)中,可以很容易地实例化和测试.另一个类(B)应该负责约束创建.单一责任原则脱颖而出!它应该是团队知识,你应该通过B访问A - 一种团队惯例.

我主要同意..

推荐阅读
殉情放开那只小兔子
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有