C ++中的单例服务类

时间:2012-08-24 10:48:33

标签: c# c++ dependency-injection prism mef

来自.NET / C#背景并且对PRISM有着深刻的了解,我真的很想在需要的时候让CompositionContainer得到一个类的这个实例。

通过ServiceLocator这个实例也是全局可访问的,这几乎可以归结为Singleton模式。

现在,我目前的项目是用c ++编写的,我正在决定如何为程序管理插件(外部dll加载和类似的东西)。

在C#中,我创建一个PluginService,将其导出为共享,并通过该实例引导所有内容(成员基本上只有一个列表,包含插件和一堆方法)。在c ++中,我显然没有CompositionContainerServiceLocator

我可能已经意识到这个的基本版本,但无论我想象的是什么都涉及使用Singletons或Global变量。对此的普遍关注似乎是:不要做全球和少数单身。

我该怎么办? (以及我对此感兴趣的是:微软在这里给我们一个关于如何编码的错误示例,或者这是一个关于单身人士是正确选择的实际情况?)

2 个答案:

答案 0 :(得分:6)

C#和C ++之间的真正区别在于全局和单身是否是好的"或者"坏"。

您概述的解决方案在C#和C ++中同样糟糕(或好)。

你似乎发现的只是不同的人有不同的意见。一些C#开发人员喜欢使用单身人士这样的东西。一些C ++程序员也有同样的感受。

有些C ++程序员认为单例是一个糟糕的主意,并且......一些C#程序员也有同感。 :)

Microsoft已经提供了许多关于如何编码的错误示例。永远不要接受他们的示例代码作为"良好做法"只是因为它说微软在盒子上。重要的是代码,而不是背后的名称。

现在,我对单身人士的主要贡献是而不是他们的全球方面。

和大多数人一样,我一般不喜欢和不信任全局,但我不会说他们应该从不被使用。在某些情况下,使全球可访问的内容更方便。它们并不常见(我认为大多数人仍然过度使用全局变量),但它们存在。

但单例的真正的问题是它们对你的代码强制执行一个不必要且通常有害的约束:它们阻止你创建一个对象的多个实例,就好像你在写这个类时一样,知道它将如何比实际的用户更好地使用。

当你写一个课程时,比如你在评论中提到的PluginService,你肯定知道如何计划使用它。您可能认为&#34;它的一个实例应该是全局可访问的(这是有争议的,因为许多类应该访问插件服务,但让我们假设我们做< / em>希望它现在是全球性的)。你可能会认为&#34;我无法想象为什么我想要有两个实例&#34;。

但问题是当你采取这个假设并主动阻止创建两个实例时。

如果从现在起两个月后你发现需要创建两个PluginServices怎么办?如果您在编写课程时采用了简单的方法,并且没有在其中构建不必要的约束,那么您也可以 采取简单的路径 now ,以及只需创建两个实例。

但如果你采取了编写额外代码的艰难道路来阻止创建多个实例,那么你现在再次必须采取艰难的道路:现在你已经回去改变你的班级。

除非您有理由否则不要在代码中构建限制:如果它使您的工作更轻松,请继续执行。如果它可以防止有害的滥用课程,请继续这样做。

但在单身案例中,它既没有做到这一点:你为自己创造了额外的工作,以防止可能完全合法的使用。

你可能有兴趣阅读this blog post我写的回答单身人士的问题。

但是为了回答如何处理您的具体情况的具体问题,我建议采用以下两种方法之一:

  • &#34;纯粹主义者&#34;方法是创建全局的ServiceLocator。将它传递给需要定位服务的人。根据我的经验,您可能会发现这比听起来容易得多。你倾向于发现它并不像你想象的那样在许多不同的地方需要它。它为您提供了解耦代码,最大限度地减少依赖关系的动机,以确保只有那些真正拥有需要的人才能获得对ServiceLocator的访问权限。这很健康。
  • 或者有实用的方法:创建ServiceLocator的单个全局实例。任何需要它的人都可以使用它,并且对于如何找到它毫无疑问 - 毕竟它是全球性的。但不要让它成为一个单身人士。可以创建其他实例。如果您永远不需要创建另一个实例,那么就不要这样做。但这会打开门,这样如果你最终需要另一个实例,你可以创建它。

在许多情况下,您最终需要一个您认为只需要一个实例的类的多个实例。围绕某些硬件的配置/设置对象,记录器或包装器都是人们经常称之为&#34;这显然应该是一个单例,没有多少实例和#34;并且在每种情况下都是没有意义的,他们错了。在许多情况下,您需要多个此类类的实例。

但最普遍适用的情况很简单:测试。

您希望确保ServiceLocator 正常工作。所以你想测试它。

如果是单身人士,那真的很难做到。一个好的测试应该在原始的隔离环境中运行,不受先前测试的影响。但是单例在应用程序的持续时间内存在,所以如果你有多个ServiceLocator测试,那么它们都会在同一个&#34; dirty&#34;例如,每次测试都可能影响下一次测试所见的状态。

相反,测试应该每个都创建一个新的,干净的ServiceLocator,这样他们就可以准确地控制它所处的状态。为此,你需要能够创建类的实例

所以不要让它成为单身人士。 :)

答案 1 :(得分:1)

当单身人士出现时,他们绝对没有错 适当。我怀疑CompositionContainer(但是 我不确定我明白它应该做什么),但是 ServiceLocator通常是一个单身人士 在任何精心设计的应用程序有两个或更多ServiceLocator 将导致程序无法正常运行(因为a 服务将在其中一个中注册,您将查找它 在另一个);以编程方式执行此操作是积极的,至少如果您这样做 赞成强大的编程。另外,在C ++中,单例成语是 用于控制初始化的顺序;除非你做 ServiceLocator单例,你不能在任何构造函数中使用它 具有静态生命期的对象。

虽然有一小群非常反对的单身狂热分子, 在更大的C ++社区中,你会发现共识有利于你 在一些非常有限的情况下,单身人士。他们很容易受到虐待 (但是,模板,动态分配和多态性也是如此),但是 他们确实非常好地解决了一个特定的问题,这将是愚蠢的 当他们是最好的时候,为了一些任意的教条理由而放弃他们 问题的解决方案。