用Singleton保护资源
Guarding resources with Singleton?
我读了不少博客文章和关于SO的回答,指出Singleton是一个糟糕的设计。以前我实现了一个单例camercontrol类。这个类控制一个连接到系统的摄像机。根据以下知识:
- 在任何情况下都不能有超过一个摄像机(摄像机制造商提供的摄像机API控制所有摄像机)。
- 在多个地方同时使用相机制造商的API在过去已经引起了问题(例如一个线程试图抓取图像,另一个线程试图设置快门速度)。我的类只提供了几个额外的方法来显示在UI中捕获的图像。将图像转发到人脸检测器,…(即它不是内存密集型的)。
我选择使这个类成为单例类是一个错误的决定吗?
单例被认为是一种气味,因为:
-
它们在道德上相当于全局变量,因此它们的使用隐藏了代码中的依赖关系,而不是通过接口显示它们。
-
它们促进了紧密耦合,因为您的代码依赖于特定类型的特定实例。如果有一天你想让你的UI对不同的相机管理器操作怎么办?
-
它们使单元测试变得困难,因为它们在程序的整个生命周期中都携带着状态。当状态从一个测试传递到另一个测试时,它可以使测试依赖于状态,这是一个非常大的气味。
你迟早可以读任何东西。不管怎样有些人说,没有根本的理由反对使用在适当情况下的单例_。在你的情况下,我有严重怀疑,至少你是这么说的。不管相机制造商的API(可能是C语言),你的客户端代码将希望将每个单独的相机视为一个单独的对象,没有什么固有的独特性相机。
的API可能适合使用单例模式相机制造商在C,你决定提供它的一个轻量级c++包装器,供(独占地)使用你的摄影课。这种轻量级的包装就是其中之一合法地使用单例——在这个世界上你不可能可以在代码中拥有该库的多个实例。(但是,通常使用Camera类地址更容易我选择使这个类成为单例类是一个错误的决定吗?
是的。
- 在任何情况下都不能有超过一个摄像机(摄像机制造商提供的摄像机API控制所有摄像机)。
这样就没有必要通过Singleton类来访问camera了。
- 在多个地方同时使用相机制造商的API在过去已经引起了问题(例如一个线程试图抓取图像,另一个线程试图设置快门速度)。
使用单例类不会为你带来任何在非单例类中无法解决的问题。
我的类只提供了几个额外的方法来显示在UI中捕获的图像。将图像转发到人脸检测器,…(即它不是内存密集型的)。
那么就没有必要创建一个类似于god的Singleton类了。
此外,你添加到Singleton类中的那些小而漂亮的helper功能,以及它们与其他代码段的交互,当驻留在具有全局状态的Singleton类中,不能在测试之间正确地设置和删除时,就不容易进行单元测试。
通过在应用程序组合根中正确使用依赖注入,具体对象的生命周期可以被管理,就好像它是一个单例,但是该对象的单个客户端不需要知道这一点。
我个人认为在适当的时候使用singleton是合理的。一般来说,它们肯定会被过度使用,但在我看来,它们对于控制硬件资源的管理器类是有用的,这就是您正在做的。
是和否
不,因为你看到的并发问题是你在处理线程时无法"安全"避免的问题。糟糕的同步机制迟早会找上门来,破坏您可爱的代码。你将需要互斥锁和信号量等来保护资源。
是的,因为单例模式对于线程来说是一个糟糕的模式。看看这个关于单例的页面,你会看到一些与之相关的陷阱。基本上,你是在自找麻烦。
关于一般的"单例是邪恶的",这是因为它使弄清楚它是如何工作的更加困难,它们是全局变量的OOP版本。假设你在某个地方有一个单例,它在15个地方被修改,你如何跟踪它?如果你有一个"真实的"对象,你就能看到它是如何在参数中传递的。单例模式打破了作用域的概念,很容易变成一团糟。
Singleton
和Monostate
模式在这方面都很有用。您的主要考虑(关于第二点)是防止多次访问,Singleton和Monostate都不能防止这一点。
是的,使它成为Singleton是一个糟糕的设计。如果你只需要一个Camera对象,那就创建一个。
如果你需要确保camera对象以不可重入的方式使用,那么这不是camera对象的责任,而是你的线程模型的责任。这是一个独立的工作。
- 具有瞬态资源的RAII类
- C++ 雷神库 - 使用资源加载器类时出现问题(不命名类型)
- 有充分的理由在h文件中使用include保护而不是cpp文件吗
- 为什么在保护模式下继承升级不起作用
- 访问被拒绝后,c++中的故障保护代码
- C++:无法访问声明的受保护成员
- 允许从 std::map 的密钥窃取资源?
- 参考资源文件VC++中的$(SolutionDir)
- 为什么您需要C++头文件的包含保护
- 如何维护资源管理器项目视图中当前可见的项目列表
- lock_guard是否保护返回值
- 如何在GTK程序运行时禁用屏幕保护程序/电源管理/屏幕消隐
- 将 std::allocate_shared 与多态资源分配器一起使用
- 使用RAII在给定次数的迭代后重新分配资源
- 资源管理设计模式
- 如何跨平台将二进制资源构建到程序中?
- 通过继承共享的静态受保护资源
- 保护资源免受逆向工程影响的最佳实践
- 通过许多流程保护硬件资源
- 用Singleton保护资源