用 Singleton 保护资源?
我读过很多博客文章和答案,指出 Singleton 是一个糟糕的设计。之前我实现了一个单例 CameraControl 类。此类控制连接到系统的相机。根据以下知识:
- 在任何情况下都不会有多个相机(相机制造商提供的相机API控制所有相机)。
- 过去,在多个地方同时使用相机制造商的 API 会引起问题(例如,一个线程尝试抓取图像,另一个线程尝试设置快门速度)。
- 我的类只提供了几个额外的方法来显示 UI 中捕获的图像。将图像转发到面部检测器,...(即它不是内存密集型的)。
我选择让这个类成为单例类是一个错误的决定吗?
I have read quite a few blog posts and answers on SO pointing to Singleton being a bad design. Previously I implemented a singleton CameraControl class. This class controls a camera which is connected to the system. Under the following knowledge:
- Under no circumstance will there be more than one camera (the camera API provided by the camera maker control all cameras).
- Using the API of the camera maker in multiple places at the same time have caused problems in the past (e.g. one thread trying to grab an image, the other thread trying to set the shutter speed).
- My class only provides several extra methods to display the image captured in a UI. Forward the image to a face detector, ... (i.e. it is not memory intensive).
Is my choice of making this class a singleton class a bad decision?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
单例被认为是一种异味,因为:
它们在道德上相当于全局变量,因此它们的使用隐藏了代码中的依赖关系,而不是通过接口揭示它们。
它们促进紧密耦合,因为您的代码依赖于特定类型的特定实例。如果有一天您希望您的 UI 针对不同的相机管理器进行操作怎么办?
它们使单元测试变得困难,因为它们在程序的整个生命周期中都带有状态。当状态在测试之间传递时,它会使测试依赖于状态,这是一个非常大的味道。
Singletons are considered a smell because:
They are the moral equivalent of global variables, and thus their use hides dependencies in code rather than revealing them through interfaces.
They promote tight coupling because your code depends on a specific instance of a specific type. What if you wanted your UI to operate against a different camera manager some day?
They make unit testing difficult because they carry state with them for the entire lifetime of the program. When state is carried across from test to test, it can make tests state-dependent, which is a very big smell.
你可以读任何东西,迟早。无论什么
有人说,没有根本理由反对使用
在适当的情况下是单例_。就你而言,我有
严重怀疑,至少从你描述的方式来看是这样。不管
相机制造商的API(可能是C语言),你的
客户端代码希望将每个单独的相机视为
一个单独的对象,并且没有什么本质上独特的东西
相机。
单例在这里可能是合适的,如果 API
相机制造商位于 C,并且您决定提供
一个轻量级的 C++ 包装器,供(独占)使用
你的相机课程。这种轻质包装纸就是其中之一
合法使用单例——世界上没有办法
您的代码中可以有该库的多个实例。
(但是,通常情况下,获得 Camera 类地址会更容易
直接使用 API,并跳过中间包装器。)
You can read anything, sooner or later. Regardless of what the
some people say, there's no fundamental reason against using
a singleton in the appropriate cases_. In your case, I have
serious doubts, at least the way you describe it. Regardless of
the API of the camera maker (which is probably in C), your
client code will want to treat each individual camera as
a separate object, and there's nothing inherantly unique about
cameras.
Where a singleton probably is appropriate here is if the API of
the camera maker is in C, and you decide to provide
a lightweight C++ wrapper for it, to be used (exclusively) by
your Camera classes. Such light weight wrappers are one
legitimate use of singletons---there's no way in the world you
can have several instances of the library in your code.
(Usually, however, it's easier to have the Camera class address
the API directly, and skip the intermediate wrapper.)
是的。
这并不意味着有必要通过 Singleton 类访问相机。
使用 Singleton 类不会给您带来任何可以让您避免在非 Singleton 类中也无法解决的问题的问题。
那么就没有必要创建一个神一般的Singleton类了。
此外,当驻留在具有全局状态的单例类中时,您添加到 Singleton 类中的那些漂亮的小帮助器功能以及它们与其他代码段的交互无法轻松进行单元测试,而全局状态无法在测试之间正确设置和拆除。
通过在应用程序组合根中正确使用依赖项注入,可以像管理单例一样管理具体对象生命周期,但该对象的各个客户端不需要知道这一点。
Yes.
That doesn't make it necessary to access the camera via a Singleton class.
Using a Singleton class will not buy you anything that saves you from those problem that you cannot also do in a non-Singleton class.
Then there's no need to create a God-like Singleton class.
Furthermore, those little nifty helper functionalities you added to the Singleton class and their interactions with other pieces of code cannot easily be unit tested when residing in a singleton class with global state that cannot properly be set up and torn down between tests.
By proper use of dependency injection in the application composition root, the concrete object lifetime can be managed as if it was a singleton, but the individual clients of that object doesn't need to know that.
我个人认为在适当的时候使用Singletons是合理的。一般来说,它们肯定可能被过度使用,但在我看来,它们对于控制硬件资源的管理器类很有用,这就是您正在做的事情。
I personally think it is reasonable to use Singletons when appropriate. There certainly may be overuse of them in general, but in my opinion they are useful for manager classes controlling hardware resources, which is what you are doing.
是和否
否,因为您看到的有关并发的问题是您在使用线程时无法“安全”避免的问题。迟早,糟糕的同步机制会回到你身边并破坏你可爱的代码。您将需要互斥体和信号量等来保护资源。
是的,因为单例对于线程来说是一个不好的模式。检查这个关于单例的页面,你会看到一些与之相关的陷阱。基本上,你是在自找麻烦。
关于一般的“单例是邪恶的”,这是因为它使得弄清楚它是如何工作的变得更加困难,它们是全局变量的 OOP 版本。假设您在某处有一个单例,它在 15 个位置进行了修改,您如何跟踪这一切?如果您有一个“真实”对象,您将能够看到它是如何在参数等中传递的。单例打破了作用域的概念,很容易转化为一团乱麻。
Yes and No
No because the problems you see about concurrency are problems you can't "safely" avoid while playing with threads. Sooner or later, bad synchronization mechanisms will come back at you and break your lovely code. You WILL need mutexes and semaphores and such to guard ressources.
Yes, because the singleton is a bad pattern to involve with threads. Check this page about singletons, you will see some pitfalls associated with it. Basically, you're asking for trouble.
Regarding the general "Singletons are evil", it is because it makes it much harder to figure out how it works, they are the OOP version of global variables. Suppose that you have a singleton somewhere, that gets modified in 15 places, how do you track it all? If you had a "real" object, you'd be able to see how it is passed around in parameters and such. The singleton breaks the concept of scope and is easy to transform into a mess.
Singleton
和Monostate
模式在这方面都很有用。您的主要考虑因素(关于第二点)是防止多次访问,并且 Singleton 和 Monostate 都不会阻止这一点。Singleton
andMonostate
patterns are both useful in this regard. Your primary consideration (regarding your second point) is to prevent multiple accesses, and neither Singleton nor Monostate prevent this.是的,使其成为单例是一个糟糕的设计。如果您只需要一个 Camera 对象,则只需创建一个即可。
如果您需要确保以不可重入的方式使用相机对象,那么这不是相机对象的责任,而是线程模型的责任。这是一项单独的工作。
Yes, making it a Singleton is a bad design. If you only need one Camera object, just make one.
If you need to ensure that a camera object is used in a non-reentrant way, than that is a responsibility not of the Camera object, but of your threading model. It's a seperate job.