I realize there is much discussion about singletons and why that are bad. That is not what this question is about. I understand the drawbacks to singletons.
我意识到有很多关于单身人士的讨论,为什么这很糟糕。这不是这个问题的实质。我理解单身人士的缺点。
I have a scenario where using a singleton is easy and appears to make sense. However, I want an alternative that will accomplish what I need without a lot of overhead.
我有这样一个场景:使用单例对象很容易,并且看起来很有意义。然而,我想要一个替代方案,它可以在不需要大量开销的情况下完成我所需要的工作。
Our application is designed as a client that typically runs on laptops in the field and communicates with a back end server. We have a status bar at the bottom of the main application. It contains a few text areas that show various statues and information as well as several icons. The icons change their image to indicate their state. Such as a GPS icon that indicates if it is connected or not as well as error state.
我们的应用程序被设计成一个客户端,通常在该领域的笔记本电脑上运行,并与后端服务器通信。在主应用程序的底部有一个状态栏。它包含一些文本区域,显示各种雕像和信息以及一些图标。图标会改变它们的图像来表示它们的状态。例如一个GPS图标,指示它是否连接以及错误状态。
Our main class is called MobileMain. It owns the status bar area and is responsible for creating it. We then have a StatusBarManager class. The StatusBarManager is currently a static class, but could also be a singleton. Here is the start of the class.
我们的主要课程叫MobileMain。它拥有状态栏区域并负责创建它。然后我们有一个StatusBarManager课程。StatusBarManager目前是一个静态类,但也可以是一个单例类。这是课程的开始。
public static class StatusBarManager
{
static ScreenStatusBar StatusBar;
///
/// Creates the status bar that it manages and returns it.
///
public static ScreenStatusBar CreateStatusBar()
{
StatusBar = new ScreenStatusBar();
return StatusBar;
}
The MobileMain asks the StatusBarManager for a StatusBar. It then uses the StatusBar. No other classes see the StatusBar, just the StatusBarManager.
手机管理员向StatusBarManager要一个StatusBar。然后它使用StatusBar。没有其他类看到StatusBar,只有StatusBarManager。
Updates to the status bar can come from pretty much anywhere in the application. There are around 20 classes that can update the text areas on the status bar and additional classes that update the icon states.
状态栏的更新几乎可以来自应用程序中的任何地方。有大约20个类可以更新状态栏上的文本区域,还有其他类可以更新图标状态。
There will only every be one StatusBar and one StatusBarManager.
只有一个StatusBar和一个StatusBarManager。
Any suggestions for a better implemention?
有什么建议可以更好的实施吗?
Some thoughts that I had:
我有一些想法:
Make the StatusBarManager an instance class. In my MobileMain class hold onto a static public instance of the StatusBarManager class. Then to do status bar updates you would call MobileMain.StatusBarManager.SetInformationText or some other method of the manager. The StatusBarManager would not be a singleton, but the MobileMain would only be creating a static instance of it. The issue here is that MobileMain now has a StatusBar and a StatusBarManager, which just manages the StatusBar it owns. Still also have a globally avaialble static instance to the StatusBarManager, just a different owner.
使StatusBarManager成为一个实例类。在我的MobileMain类中,保持StatusBarManager类的静态公共实例。然后进行状态栏更新,您可以调用MobileMain.StatusBarManager。SetInformationText或管理器的其他方法。StatusBarManager不是单例的,但是MobileMain只会创建它的静态实例。这里的问题是,MobileMain现在有一个StatusBar和StatusBarManager,它只管理它拥有的StatusBar。对于StatusBarManager仍然有一个全局通用的静态实例,只是不同的所有者。
Another idea was to use something like an EventEggregator class. I've never used one, but have read about them. I guess the concept is that it would be a globally available class. In each class that wants to update the status bar it would publish a StatusBarUpdate event. The StatusBarManager would be the only classes subscribing to the StatusBarUpdate event, and receive all of the notifications. I've read though that can end up with leaks with this approach if you are not carefull with unsubscribing from events when cleaning up objects. Is this approach worth looking into?
另一个想法是使用类似于EventEggregator类的东西。我从未用过,但读过有关它们的书。我想这个概念是它是一个全局可用的类。在每个想要更新状态栏的类中,都会发布一个StatusBarUpdate事件。StatusBarManager将是订阅StatusBarUpdate事件的惟一类,并接收所有通知。我读到过,如果您在清理对象时没有从事件中取消订阅,那么这种方法可能会导致泄漏。这种方法值得研究吗?
2
Having a StatusBar class or a StatusBarManager class or not is not a big deal. But having many classes in your app know about StatusBars and StatusBarManagers is a bad idea, it will cause strong coupling, and some day probably pain.
是否有StatusBar类或StatusBarManager类并不是什么大问题。但是在你的应用程序中有很多类知道statusbar和StatusBarManagers是一个坏主意,它会导致强耦合,并且有一天可能会很痛苦。
How?
如何?
Imagine that the components that currently report status to a status bar have to be reused in another app that - uses a text console to report status? - reports status to multiple places? or - doesn't report status at all!
假设当前向状态栏报告状态的组件必须在另一个使用文本控制台报告状态的应用程序中重用?-向多个地方报告状态?或者根本不报告状态!
Best alternative: -Event listening. Expose a Status Changed event on your class (you can use a callback), or perhaps on an existing shared resource that your classes have in common. Other parties, like your status bar, can subscribe to the event. And should unsubscribe whenever the subscription is no longer needed/valid, to prevent leaks, as you mention!
最好的选择:事件监听。在类中公开一个状态更改事件(可以使用回调),或者可能是在您的类共有的现有共享资源上。其他的团体,比如你的状态栏,可以订阅这个活动。并且当订阅不再需要/有效时应该取消订阅,以防止泄漏,正如您所提到的!
-Since you've tagged WPF, for WPF, having a dependency property 'StatusText', might seem like another tempting option, with this approach when you have multiple status properties, you need a way of figuring out which one is telling you the most interesting status that needs to be displayed on your status bar now! Which could be a binding, multibinding (blech, complexity), or dependency property changed event handler.
因为你标记WPF为WPF,依赖房地产“StatusText”,似乎是另一个诱人的选择,使用这种方法,当你有多个状态属性,您需要一种方法找出哪一个是告诉你最有趣的地位在你现在的状态栏需要显示的!可以是绑定、多绑定(blech、复杂性)或依赖属性更改的事件处理程序。
However - I would advise you to keep DependencyObjects and DependencyProperties limited to your UI layer as much as possible. The reason is that they rely implicitly on a Dispatcher on the UI thread, and so can't be adapted easily for non-UI chores.
但是——我建议您尽可能将DependencyObjects和DependencyProperties限制在UI层中。原因是它们隐式地依赖于UI线程上的分派器,因此不能轻松地适应非UI事务。
Since there are many different parts of your app you may also possibly find it's reasonable to have a combination of both of these, using some one place and some another.
由于你的应用有很多不同的部分,你可能也会发现把这两个部分结合在一起是合理的,使用不同的地方。
3
I prefere Static classes that hold your objects. So the amount of objects you can access is restircted by the interface your static class offers. Static is not bad as long as your application still scales.
我喜欢包含对象的静态类。因此,可以访问的对象数量由静态类提供的接口重新激发。只要您的应用程序还在扩展,静态也不是坏事。
Another good alternative to singletons is the Monostate pattern, where you have a class that implements private static fields to represent "singleton" behavior.
单例的另一种很好的替代方法是单状态模式,其中有一个实现私有静态字段来表示“单例”行为的类。
See:
Monostate
Monostate vs. Singleton
参见:单态单态和单态
UPDATE: It often helps me to keep a REST like api in mind, even for internal program structures. Having one class that is updated from everywhere and sends notices to everybody is hard to control in respect to raise conditions and infinity loops (Update -> Event -> Update -> ...)
更新:它经常帮助我记住api,即使是内部程序结构。对于提高条件和无限循环(Update -> Event -> Update ->…)来说,拥有一个从各处更新并向每个人发送通知的类是很难控制的。
Build an (static or not) Status bar interface that you can access where you need it. Through a Static class where you get access to your Status bar interface or by dependency injection if you use such techniques (not recommended for smaller projects). Every call to your status bar interface has to be independent from any events that might be raised by the Status bar to avoid further issues with raise conditions. Think of the status bar interface like a website that can be called from other parts of the program to push and pull information.
构建一个状态栏接口,您可以在需要时访问它。通过静态类,您可以访问状态栏接口或依赖注入,如果您使用这些技术(不推荐用于较小的项目)。对状态栏接口的每次调用都必须独立于状态栏可能引发的任何事件,以避免引发条件的进一步问题。想象一下状态栏界面,就像一个网站,可以从程序的其他部分调用,以推动和拉动信息。
1
You could simply use the Observer
pattern and add the StatusBar
as a listener to your 20 objects. This will eliminate the singletons and better follow SRP and DIP, but you will have to consider whether it is worth the effort. A singleton may be better if the indirection adds too much complexity and dependency injection is not possible.
您可以简单地使用Observer模式,并将StatusBar添加为您的20个对象的侦听器。这将消除单例,并更好地遵循SRP和DIP,但是您必须考虑这样做是否值得。如果单向添加过多的复杂性和依赖注入是不可能的,那么单例可能会更好。
public class StatusBar implements StatusListener {
}
public interface StatusListener {
public statusChanged(String newStatus)
}
0
Classes will depend implicitly on any use singleton and explicitly to any parameters in the constructor. I would suggest adding an interface to the singleton, so just the methods needed would be exposed to the classes using the IStatusBar. This is more code, but will ease unit testing.
类将隐式地依赖于任何单例使用,并显式地依赖于构造函数中的任何参数。我建议向singleton添加一个接口,这样只需使用IStatusBar将所需的方法公开给类。这是更多的代码,但是可以简化单元测试。
-1
It's hard to give advice without knowing more of your application's architecture, but perhaps you should consider dependency injection. For example, pass a StatusBar instance to the constructor of each class that directly uses it.
如果不了解应用程序的架构,就很难给出建议,但也许您应该考虑依赖项注入。例如,将StatusBar实例传递给直接使用它的每个类的构造函数。