正确使用单例设计模式

8
我正在运行一个服务器,有时需要搜索客户端查询的内容。我想将客户端查询写入磁盘以便记录,但我不想让搜索变得更加缓慢。(搜索已经是瓶颈了...)
因此,当客户端执行搜索时,我让客户端线程向单例线程发送消息,该线程将处理磁盘写入,而客户端线程继续处理客户端的请求。这样,磁盘上的文件不会遇到同步问题,并且不会减慢客户端的体验。
我在这里有一个概念性问题:在这种情况下,单例模式是否适用?最近我的编程中使用了太多的单例设计模式,我想确保我在使用它时符合其预期用途。
非常感谢任何反馈。

3
没有看到你的整体架构,很难回答这个问题。单例模式存在一些缺点(会导致单元测试方面的困难等),你需要自己判断它们是否相关…… - Oliver Charlesworth
1
谢谢您的快速回复,Oli;我已经了解了单元测试的困难之处,但是并没有理解其整体影响。为什么避免全局状态如此重要?例如,如果磁盘上只有一个文件供程序写入,难道不希望确保它不能同时被不同的部分访问吗? - Sal
全局状态的存在可能会使依赖注入变得困难(这是模拟测试的基础)。请观看此演讲以获取更多详细信息:http://googletesting.blogspot.com/2008/11/clean-code-talks-global-state-and.html。 - Oliver Charlesworth
1
你使用的是哪种编程语言?使用Singleton如何帮助处理同步问题,防止经验减速?是否会启动单独的进程来处理这个问题? - cmbuckley
可能是单例模式有哪些特定的合法用途?的重复问题。 - just somebody
显示剩余3条评论
1个回答

7

单例模式被过度使用且存在一些问题(单元测试是经典例子),但像设计中的所有事物一样,您需要权衡特定场景的利弊。单例模式确实有其用途。还有一些选项可以帮助您获得单例行为,同时缓解某些固有问题:

拦截(通常被称为面向方面的编程,尽管我看到关于它们并不完全相同的争论...目前找不到我读过的文章)肯定是一种选择。您可以使用任何组合的构造注入、装饰器模式、抽象工厂和控制反转容器。我对Java IoC容器不了解,但有一些.Net容器允许自动拦截(我相信Spring.Net会,所以可能Spring(Java)内置了这个功能)。这对于任何需要在多个层中执行某些类型的操作(安全性、日志记录等)的横切关注非常方便。此外,大多数IoC容器允许您控制生命周期管理,因此您可以将记录器视为单例,而无需手动实现单例模式。

总之,如果单例适用于您的情况(从您的描述中似乎是合理的),请使用它。只是确保您已经权衡了利弊。您可能希望尝试不同的方法并比较两者。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接