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

关于设计模式:我什么时候应该使用单身人士?

如何解决《关于设计模式:我什么时候应该使用单身人士?》经验,为你挑选了11个好方法。

荣耀的全球变量 - 成为一个荣耀的全球阶级.有人说打破面向对象的设计.

给我一些场景,除了好的旧记录器,使用单例是有意义的.



1> CodingWithou..:

在我追求真相的过程中,我发现使用Singleton实际上很少有"可接受"的理由.

在互联网上一次又一次地出现的一个原因是"日志记录"类(你提到过).在这种情况下,可以使用Singleton而不是类的单个实例,因为项目中的每个类通常需要反复使用日志记录类.如果每个类都使用此日志记录类,则依赖项注入会变得很麻烦.

日志记录是"可接受的"Singleton的一个特定示例,因为它不会影响代码的执行.禁用日志记录,代码执行保持不变.启用它,同样相同.Misko在单根的根本原因中将其置于以下方式,"这里的信息以一种方式流动:从您的应用程序进入记录器.即使记录器是全局状态,由于没有信息从记录器流入您的应用程序,因此记录器是可接受的."

我相信还有其他正当理由.Alex Miller在" 模式我讨厌 "中讨论了服务定位器和客户端UI也可能是"可接受的"选择.

在Singleton阅读更多我爱你,但你让我失望.


@ArneMertz我猜[this](http://geekswithblogs.net/AngelEyes/archive/2013/09/08/singleton-i-love-you-but-youre-bringing-me-down-re-uploaded.aspx)是这个.

2> metao..:

Singleton候选人必须满足三个要求:

控制对共享资源的并发访问.

将从系统的多个不同部分请求访问资源.

只能有一个对象.

如果您提出的Singleton只有一个或两个这样的要求,重新设计几乎总是正确的选择.

例如,不太可能从多个位置("打印"菜单)调用打印机假脱机程序,因此您可以使用互斥锁来解决并发访问问题.

简单的记录器是可能有效的Singleton的最明显的例子,但是这可以随着更复杂的记录方案而改变.


我想你错过了"候选人"这个词.Singleton候选人必须满足这三个要求; 只是因为某些东西符合要求,并不意味着它应该是一个单身人士.可能还有其他设计因素:)
我不同意第2点.第3点并不是一个真正的理由(仅仅因为你不能表示你应该这样做)而且1是一个好点,但我仍然没有看到它的使用.可以说共享资源是磁盘驱动器或数据库缓存.您可以添加另一个驱动器或让数据库缓存专注于另一个事物(例如,一个线程的专用表的缓存,而另一个更通用).

3> Paul Croarki..:

读取应该只在启动时读取并将它们封装在Singleton中的配置文件.


类似于.NET中的`Properties.Settings.Default`.
@Paul,"no-singleton camp"将声明配置对象应该简单地传递给需要它的函数,而不是让它可以全局访问(也就是单例).
@PaulCroarkin你能否扩展一下并解释这有什么好处?
不同意.如果将配置移动到数据库,一切都搞砸了.如果配置的路径依赖于该单例之外的任何东西,那么这些东西也需要是静态的.

4> Vincent Ramd..:

您需要管理共享资源时使用单例.例如打印机假脱机程序.您的应用程序应该只有一个假脱机程序实例,以避免对同一资源的请求冲突.

或者数据库连接或文件管理器等.


我听过这个打印机假脱机示例,我认为这有点蹩脚.谁说我不能有多个假脱机?什么是打印机假脱机呢?如果我有不同类型的打印机不能冲突或使用不同的驱动程序怎么办?
它只是一个例子......对于任何人用作例子的任何情况,你将能够找到一个替代设计,使这个例子无用.让我们假设假脱机程序管理由多个组件共享的单个资源.有用.

5> Martin Becke..:

只读单例存储一些全局状态(用户语言,帮助文件路径,应用程序路径)是合理的.小心使用单例来控制业务逻辑 - 单个几乎总是最终成为多个


用户语言只能是单例,假设只有一个用户可以使用该系统.

6> Federico A. ..:

管理数据库的连接(或连接池).

我还会用它来检索和存储外部配置文件的信息.


@Ken你几乎在所有情况下都希望这家工厂成为单身人士.
你真的不需要一个单身人士.它可以注射.
数据库连接生成器不是工厂的示例吗?
@Federico,"no-singleton camp"将声明这些数据库连接应该简单地传递给需要它们的函数,而不是让它们全局可访问(也就是单例).

7> Dave Markle..:

使用单例的一种方法是覆盖必须有一个"代理"控制对资源的访问的实例.单身人士在记录器方面表现优异,因为他们可以代理访问一个文件,这个文件只能写入.对于像日志记录这样的东西,它们提供了一种将写入抽象为日志文件的方法 - 你可以将缓存机制包装到你的单例等等......

还要考虑一种情况,你有一个应用程序有许多windows/threads/etc,但需要单点通信.我曾经用一个来控制我希望我的应用程序启动的作业.单身人员负责序列化工作并将其状态显示给感兴趣的程序的任何其他部分.在这种情况下,你可以看一个单例就像在你的应用程序中运行的"服务器"类...... HTH


记录器通常是单件,因此不必传递记录对象.任何适当的日志流实现都将确保并发写入是不可能的,无论它是否是Singleton.

8> Adam Ness..:

在管理对整个应用程序共享的资源的访问时,应使用单例,并且可能具有同一类的多个实例是破坏性的.确保对共享资源线程安全的访问是这种模式至关重要的一个非常好的例子.

使用单身人士时,你应该确保你不会意外地隐藏依赖关系.理想情况下,单个应用程序(如应用程序中的大多数静态变量)在执行应用程序的初始化代码期间设置(静态void Main()用于C#可执行文件,static void main()用于java可执行文件)然后传入所有其他需要实例化的类.这有助于您保持可测试性.



9> daalbert..:

我认为单例使用可以认为与数据库中的多对一关系相同。如果您的代码中有许多不同的部分需要使用一个对象的单个实例,那么使用单例才有意义。



10> Schwern..:

单例的一个实际例子可以在Test :: Builder中找到,这个类几乎支持每个现代Perl测试模块.Test :: Builder singleton存储和代理测试过程的状态和历史(历史测试结果,计算运行测试的数量)以及测试输出的去向.这些都是协调由不同作者编写的多个测试模块在一个测试脚本中协同工作所必需的.

Test :: Builder的单身人士的历史是教育性的.调用new()总是给你相同的对象.首先,所有数据都存储为类变量,对象本身没有任何内容.这一直有效,直到我想用自己测试Test :: Builder.然后我需要两个Test :: Builder对象,一个设置为虚拟对象,捕获并测试其行为和输出,一个是真正的测试对象.此时,Test :: Builder被重构为一个真实的对象.单例对象存储为类数据,并new()始终返回它. create()添加了一个新对象并启用测试.

目前,用户希望在自己的模块中更改Test :: Builder的某些行为,但是让其他人保持独立,而测试历史在所有测试模块中保持共同.现在发生的事情是单片Test :: Builder对象被分解成更小的片段(历史,输出,格式......),其中一个Test :: Builder实例将它们收集在一起.现在,Test :: Builder不再是一个单身人士.它的组成部分,如历史,可以.这将单身人士的灵活必要性推向了一个层次.它为用户提供了更多的混合和匹配件的灵活性.较小的单例对象现在可以只存储数据,其包含的对象决定如何使用它.它甚至允许非Test :: Builder类通过使用Test :: Builder历史记录和输出单例来进行.

似乎是在数据协调和行为灵活性之间存在推动和拉动,这可以通过将单例放在仅具有最小行为的共享数据来减轻,以确保数据完整性.



11> Dean J..:

当您从数据库或文件中加载配置属性对象时,将其作为单例是有帮助的。没有理由继续读取服务器运行时不会改变的静态数据。


为什么不只加载一次数据并根据需要传递配置对象?
推荐阅读
拾味湖
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有