单例或将指针传递给管理器中的静态引用

时间:2014-04-04 14:40:18

标签: c++ singleton

我有一个连接管理器,它当前有一个类的静态引用,该类保存在类的私有部分的连接管理器中。指向此类的指针将传递给所有连接,并且可以将其用于实用程序。

现在这个类指针对于孩子们并不是立即有用,但它对于孩子们自己的孩子很有用,所以所有这一切都是传递给它的。

现在我想知道,因为这个实用程序类只有一个实例,我应该为所有这些传递指针烦恼,或者最好让类成为单例,并且每个需要它的类都可以只需使用静态getInstance()方法。这意味着不关心它的类不需要知道它。

有很多类型的连接(30+),它们都不关心实用程序类。 但是,他们将使用关注实用程序类的类(目前只有2个)。

我不确定每种类型的连接是否应该加重自己不关心的事情,只是为了它可能会使用的几个类。

3 个答案:

答案 0 :(得分:2)

Singletons和静态字段通常被认为是邪恶的。为什么它仍然是静态的?它可能会发生,所以有一天你需要每个连接管理器都有自己的参考。

我能想到的最好的想法是首先使参考非静态。然后,忘记使用单身人士。从这一点开始,您应该开始考虑如何以最优雅的方式实现这一点。

我不知道你的类的性质,但对我而言,每个连接都应该有一个引用它的连接管理器的引用(或指针),这听起来是合理的。以防万一。

然后,连接管理器应该为想要访问该实用程序类的任何人提供一个getter。连接本身应该传递给连接管理器或实用程序类的引用,具体取决于更有意义的内容。

将连接管理器的引用传递给连接的公共祖先的构造函数(如果有的话)(它应该是)也是有意义的。这样,你不再有30多个类来引用他们并不真正需要的东西,而是只有一个基于它们的抽象类。

如果你真的想做类似单例的事情,那么最好有一种带有返回引用的参数的静态方法,而不仅仅是静态方法:

static UtilityClass *getInstance(int id);
// not static UtilityClass *getInstance();

即使您现在不使用id参数,也可能在以后需要多个实例时非常有用。您可以使用某种表或哈希映射将id映射到实例。您甚至可以添加一个方法来创建或替换特定id的实例,这对于单元测试非常有用。请注意,这种方法至少仍具有单例模式的以下缺点:

  • 容易出现各种线程问题。
  • 它仍然隐藏了您的类的依赖关系:也就是说,您无法通过查看其API来说明类所使用的内容。

如果不查看代码,很难提供更多建议。

答案 1 :(得分:1)

如果我理解正确,在顶层有一个连接管理器。它包含一个静态类,稍后会有用。

下一层是一个类的许多实例,它们为上述经理管理的每个连接提供服务。

其中每一个都可以使用一些实用程序类实例,这些实例类希望从Connection Manager访问信息(在这种情况下,你将它作为静态对象包装起来)。

问题是第三层的最佳状态应该如何才能获得对Connection Manager所包含信息的访问权。

我打电话给他们:经理(包含'静态课程') - >连接 - >效用

我的建议是让Connections接受对拥有它们的Manager的引用。如果没有它们,它们就不会存在或不存在它们由它们管理。他们反过来需要构建需要来自Connection Manager(其中包含的静态类)的特定信息的对象。

因此,当Connection构造Utility类时,Utility类只需要操作它们所需的一些信息(在这种情况下,一个类的引用参数恰好在Manager中是静态的)。他们也应该参考这个。 Connection具有Manager类引用,并且能够为Utility提供操作所需的一些信息。

我建议采用这种方法的原因是:

  • 连接/公用事业类并不关心经理是否是单身人士(如果您需要多个经理人,可以在以后打开)
  • 实用程序并不关心静态类是否为静态。他们只需要参考他们需要的特定课程。
  • Manager决定如何分配它或其包含的数据。

最后:

  • 唯一有理由了解其他两个主要类的类是Connections类。它可能知道哪个管理器正在管理它(以及一些接口信息)似乎是合理的。它还知道它将需要哪些实用程序类以及它们在构造参数和其他接口要求方面需要什么。

要设置它可能会有一些funkiness包括和类可能必须相互公开接口,但这只是标准票价。

我的2c。

答案 2 :(得分:1)

Singleton vs. Static

单例使用的一个很好的例子:你只希望为一个类运行一个实例,例如纹理管理器,着色器管理器,连接池管理器等(参见新出现的模式:)

作为一个例子,我们来看一个连接池管理器:我们想要创建一个连接池,由我们的代码中需要连接的任何其他对象管理和重用,所以我们创建了一个ConnectionPoolManager单身类,比方说,32个连接。现在,这允许每个需要连接的对象使用来自getFreeConnection单例的方法(例如ConnectionPoolManager)来检索有效连接,然后可以根据需要使用该连接。这允许ConnectionPoolManager成为代码中唯一与启动停止和管理代码连接有关的代码部分。

单例和静态类都可以通过线程安全的方式实现,但是单例具有优势,因为它们可以实现接口(公共),派生自其他类(不太常见),单例可以是以与任何其他对象完全相同的方式传递(至少是对它的引用),其中静态类只能实现静态方法。

关于您的具体案例,您表明从30多个班级只有一对夫妇需要实用班级:对singletonstatic class的依赖完全取决于您的设计和风格。如果你想要一种多功能的方式,以后有可能改变,我会使用单身人士。如果你知道静态类就足够了,以后就不需要重新设计了,那就去吧,或者,如果你特别喜欢其中一个,那么就使用那个。可能还有硬件/软件限制和细节推荐一个,但目前听起来并非如此。

如果您需要更多信息,或者您认为可能会以某种方式影响您的选择,请告知我们,我可以提供有关每种方法的优缺点信息,以满足您的需求:)