辛格尔顿:应该如何使用它
编辑:从另一个问题,我提供了一个答案,有很多关于单身人士的问题/答案的链接:关于单身人士的更多信息在这里:
所以我已经读过线程Singletons:好的设计还是拐杖?
争论仍然激烈。
我将Singletons看作设计模式(好的和坏的)。
Singleton的问题不是模式,而是用户(对不起每个人)。 每个人和他们的父亲都认为他们可以正确地实施一项(并且从我所做的多次采访中,大多数人不能)。 同样因为大家都认为他们可以实现一个正确的单身人士,他们滥用模式,并在不合适的情况下使用它(用单身人士代替全局变量!)。
所以需要回答的主要问题是:
我对这篇文章的希望是我们可以在一个地方收集(而不是必须谷歌和搜索多个网站)何时(以及如何)正确使用单例的权威来源。 同样适合的是反用例和常见不良实现的列表,解释了为什么它们不能工作并且为了良好实现它们的弱点。
所以让球滚动:
我会握住我的手,说这是我用的,但可能有问题。
我喜欢“Scott Myers”在他的着作“Effective C ++”中处理这个主题,
好的情况下使用单身人士(不是很多):
/*
* C++ Singleton
* Limitation: Single Threaded Design
* See: http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf
* For problems associated with locking in multi threaded applications
*
* Limitation:
* If you use this Singleton (A) within a destructor of another Singleton (B)
* This Singleton (A) must be fully constructed before the constructor of (B)
* is called.
*/
class MySingleton
{
private:
// Private Constructor
MySingleton();
// Stop the compiler generating methods of copy the object
MySingleton(MySingleton const& copy); // Not Implemented
MySingleton& operator=(MySingleton const& copy); // Not Implemented
public:
static MySingleton& getInstance()
{
// The only instance
// Guaranteed to be lazy initialized
// Guaranteed that it will be destroyed correctly
static MySingleton instance;
return instance;
}
};
好。 让我们一起讨论一下批评和其他实现。
:-)
你们都错了。 阅读问题。 回答:
在以下情况下使用单例:
如果出现以下情况,请勿使用Singleton:
如何创建最好的单身人士:
单身人士让你能够在一个班级中结合两个不好的特质。 这在几乎每一个方面都是错误的。
一个单身人士给你:
第一个是直截了当的。 全局通常是不好的。 除非我们真的需要它,否则我们不应该让全局对象可用。
第二个听起来可能是有道理的,但让我们考虑一下吧。 您最后一次意外地*创建新对象而不是引用现有对象的时间是什么时候? 由于这是C ++标记的,因此我们使用该语言的示例。 你是否经常意外地写信
std::ostream os;
os << "hello worldn";
当你打算写
std::cout << "hello worldn";
当然不是。 我们不需要防范此错误,因为这种错误不会发生。 如果是这样,正确的回答是回家睡觉12-20小时,并希望你感觉更好。
如果只需要一个对象,只需创建一个实例。 如果一个对象应该是全局访问的,那么把它变成全局的。 但这并不意味着不可能创建其他实例。
“只有一个实例是可能的”约束并不能真正保护我们免受可能的错误。 但它确实使我们的代码非常难以重构和维护。 因为后来我们经常发现我们确实需要多个实例。 我们有多个数据库,我们有多个配置对象,我们需要多个记录器。 我们的单元测试可能希望能够在每个测试中创建和重新创建这些对象,以举一个常见示例。
因此,一个单应使用当且仅当,我们既需要的特质它提供了:如果我们需要全球性的访问(这是罕见的,因为全局一般气馁),我们需要防止任何人曾经创造的多个实例类(这听起来像是一个设计问题)。 我能看到的唯一原因是,如果创建两个实例会破坏我们的应用程序状态 - 可能是因为该类包含一些静态成员或类似的愚蠢行为。 在这种情况下,显而易见的答案是修复该课程。 它不应该依靠唯一的实例。
如果你需要全局访问一个对象,使它成为一个全局的,就像std::cout
。 但是不要限制可以创建的实例的数量。
如果你确实需要将一个类的实例数限制为一个,并且没有办法可以安全地处理创建第二个实例,然后执行该操作。 但是,也不要让它可以全球访问。
如果你确实需要两种特质,那么1)把它变成一个单身,2)让我知道你需要什么,因为我很难想象这样的情况。
单身问题不是它们的实现。 这是他们混淆了两个不同的概念,这两个概念都显然是不可取的。
1)单身人士提供一个对象的全局访问机制。 尽管在没有明确定义的初始化顺序的语言中,它们可能稍微多一些线程安全或稍微可靠一些,但这种用法仍然是全局变量的道德等价物。 这是一个全球性的变量,它使用了一些尴尬的语法(foo :: get_instance()而不是g_foo),但它具有完全相同的目的(在整个程序中可以访问单个对象)并具有完全相同的缺点。
2)单例防止一个类的多个实例化。 IME很少,这种功能应该被烘焙到一个类中。 它通常是一个更有关联的事物; 许多被认为是唯一的东西实际上只是一种。 IMO更适当的解决方案是只创建一个实例 - 直到您意识到您需要多个实例。
链接地址: http://www.djcxy.com/p/8823.html