9

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.

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.

public static class StatusBarManager
{
    static ScreenStatusBar StatusBar;

    /// <summary>
    /// Creates the status bar that it manages and returns it.
    /// </summary>
    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.

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.

There will only every be one StatusBar and one 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.

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?

WPFNewbie
  • 2,332
  • 6
  • 29
  • 44
  • 1
    This post has a number of questions in it. Pick one at a time to get answered. – N_A May 02 '12 at 12:20
  • have you thought about using MEF or Unity? There you register a single instance of anything you want with a container so you can retrieve it somewhere else. – stijn May 02 '12 at 12:27
  • A good read, related to the naming of StatusBarManager; http://www.codinghorror.com/blog/2006/03/i-shall-call-it-somethingmanager.html – Patrick May 02 '12 at 12:41
  • The inversion of control principle comes into play here. I would say that you should invert the dependency of your 20+ classes to StatusBarManager. One way of doing this would be the observer pattern, where the StatusBarManager observes and responds to the state changes accordingly (an EventAggregator would be one way to achieve this). – MattDavey May 02 '12 at 12:44
  • 1
    Singleton is not always bad, FWIW. If you have the problem Singleton is meant to solve, use it. Its gotten a bad rap though because people tried to use Singleton outside of the problem it tries to solve, which would cause disaster with any design pattern. – Andy May 02 '12 at 12:52
  • Patrick, thanks, we do using SomethingManager a lot. In some cases it is appropriate as the classes performs numerous actions, but then perhaps we should be breaking the class up into more specialized classes. I'll rename our class to StatuBarUpdater, since it is only responsible for updating the status bar. – WPFNewbie May 02 '12 at 13:02
  • MattDavey, how would you set this up though. Would every class that updates the status bar have to implement and event that the status bar would subscribe to. Then the classes doing the update would raise that event? If so, this creates a lot of coding for events and also means that the StatusBarManager would have to know about everyone that updates it to subscribe to their events. I haven't yet implemented an EventAggregator, just read about them, would it be worthwhile investing the time in learning about them? Do they provide lots of use? – WPFNewbie May 02 '12 at 13:05
  • @WPFNewbie Affirmative on your first point. It would require some serious thought to abstract all of those events such that they can all be treated in the same way (although responded to differently) by the StatusBarManager. Also affirmative on your second point, but the EventAggregator would allow you two break the tight coupling between the StatusBarManager and the 20+ status updaters. You could use DI to inject the event aggregator implementation (as a singleton managed by the DI container) into the StatusBarManager and the 20+ updaters respectively. – MattDavey May 02 '12 at 14:50

5 Answers5

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 -> ...)

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.

Community
  • 1
  • 1
Tarion
  • 14,013
  • 11
  • 61
  • 98
  • So to recap, you don't see anything wrong with our current designer where the StatusBarManager is a static class? I looked through the other links you included. As for monostate, the issue is that I don't want it to be transparent. Everyone should know that there is only one status bar and that is what they are updating. That is my feeling on it anyway. My main issue with static classes and singltons is reusability of the classes referencing them. You now have reference to a global class that would have to be satisified if you reused the class in another project. – WPFNewbie May 02 '12 at 12:55
  • Usually the "bad thing" on statics is. When you have many classes depend on some Static classes which makes refactoring and testing impossible. If not your Statusbar but your interface to the statusbar is static, the statusbar can still be exchanged for testing cases. The static class will be small enough to rewrite it as needed. – Tarion May 02 '12 at 13:22
  • If you want to get rid of the static class I only see Dependency Injection (Property or Constructor Injection) as possibility. Constructor Injection will need the StatusBar (Or StatusBarHandler) in every constructor which might be too much. PropertyInjection will rely on the fact, that you inject the property. Thats usually done by a MicroKernel. The whole program will rely on that Kernel. DI is a good way if you need testable code but can confuse you in smaller projects because it's harder to debug. – Tarion May 02 '12 at 13:24
  • Any comments on the suggestion of have MobileMain contain a static reference an instance StatusBarManager class? Some of the classes that update the status bar are also singletons, like our CommunicationManager which is responsible for updating the transmission icon state whenever it is communicating to the server. For DI, would in CommunicationManager I have a property for StatusBarManager, then in MobileMain I would have a command like CommunicationManager.StatusBarManager = _statusBarManager, with _statusBarManager now representing an instance of the manager owned by MobileMain? – WPFNewbie May 02 '12 at 13:39
  • Instead of linking it static from the MobileMain you can make the Function/Property in the StatusBarManager static. Than you don't get an extra dependency and more responsibilities to your MobileMain which will not scale well. What advantage would you have when you access the StatusBar through StatusBarManager through MobileMain? DI works like you described but is often implemented more dynamically using attributes and/or containers where you register your instances (like StatusBar). Then the MobileMain will configure the container like: _container.RegisterSingleton(); – Tarion May 03 '12 at 12:58
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.

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.

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.

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.

Tim Lovell-Smith
  • 13,077
  • 11
  • 67
  • 89
  • 1
    Thanks for the answer. I wanted to clarify my understanding of your best approach. We should place a StatusChanged event in each class that updates the status bar. The raise that event which will have the status bar subscribing to it. Is this what you are suggesting? If so, the StatusBar or StatusBarManager must have knowledge of every class updating it to be able to subscribe to the StatusChanged event. I do understand the issue with having all our classes having knowledge of the StatusBarManager for reusability, which is in part why I want to make the change. – WPFNewbie May 03 '12 at 12:16
  • I also considered using a NotificationManager, which may fall under your suggestion of a shared resource. It could handle all notifications, including the status bar. What would be ideal is to have an interface, so the classes could be reused in any project as long as they had a class that implemented the INotifier interface, but I don't think you can do that with a singleton or static class. – WPFNewbie May 03 '12 at 12:20
  • Ah - there's a good point - StatusBar doesn't actually need to know about every class! You can instead have a StatusBar.UpdateStatus() method, and then in a higher layer class (which has knowledge of everything for other reasons anyway), do some binding to make all the event handlers to call that method. – Tim Lovell-Smith May 07 '12 at 04:54
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.

public class StatusBar implements StatusListener {
}

public interface StatusListener {
   public statusChanged(String newStatus)
}
Garrett Hall
  • 27,772
  • 10
  • 56
  • 73
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.

-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.

Watsontap
  • 132
  • 8
  • That sounds like a rough idea. Now you have to pass extra parameters into all your objects at construction time, add extra code in your constructors to initialize them, extra fields into objects all over the place to store many references to what is actually a single object, and all of your types can no longer be compiled without the StatusBar type. – Tim Lovell-Smith May 03 '12 at 07:07