Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Help me remove a Singleton: looking for an alternative

Background: I have some classes implementing a subject/observer design pattern that I've made thread-safe. A subject will notify it's observers by a simple method call observer->Notified( this ) if the observer was constructed in the same thread as the notification is being made. But if the observer was constructed in a different thread, then the notification will be posted onto a queue to be processed later by the thread that constructed the observer and then the simple method call can be made when the notification event is processed.

So… I have a map associating threads and queues which gets updated when threads and queues are constructed and destroyed. This map itself uses a mutex to protect multi-threaded access to it.

The map is a singleton.

I've been guilty of using singletons in the past because "there will be only one in this application", and believe me - I have paid my penance!

One part of me can't help thinking that there really will be only one queue/thread map in an application. The other voice says that singletons are not good and you should avoid them.

I like the idea of removing the singleton and being able to stub it for my unit tests. Trouble is, I'm having a hard time trying to think of a good alternative solution.

The "usual" solution which has worked in the past is to pass in a pointer to the object to use instead of referencing the singleton. I think that would be tricky in this case, since observers and subjects are 10-a-penny in my application and it would very awkward to have to pass a queue/thread map object into the constructor of every single observer.

What I appreciate is that I may well have only one map in my application, but it shouldn't be in the bowels of the subject and observer class code where that decision is made.

Maybe this is a valid singleton, but I'd also appreciate any ideas on how I could remove it.

Thanks.

PS. I have read What's Alternative to Singleton and this article mentioned in the accepted answer. I can't help thinking that the ApplicationFactory it just yet another singleton by another name. I really don't see the advantage.

like image 924
Steve Folly Avatar asked Nov 12 '09 21:11

Steve Folly


People also ask

What is the alternative for singleton design pattern?

The monostate pattern is sometimes known as a conceptual singleton or the syntactic sugar over the singleton pattern. It avoids all the issues that come with having only one instance of a class. Yet, all the instances share the same data.

How do I uninstall singleton?

And deletion of singleton class object would be allow only when the count is zero. To design C++ delete singleton instance, first, we need to make the singleton class destructor private, so, it can not be accessed from outside of the class. Hence, user cannot delete the singleton instance using the keyword “delete”.

What is the alternative for singleton in Java?

So, you can see that Dependency Injection offers a better alternative to Singleton Pattern in Java.

Does singleton class need destructor?

Because all the member functions of this class are static and the class has no instance variables, it is not required that the class be instantiated. The member functions can be used without an instance of the class. Thus there is no need to implement constructors or a destructor for this class.


2 Answers

If the only purpose to trying to get rid of the singleton is from a unit test perspective, maybe replacing the singleton getter with something that you can swap in a stub for.

class QueueThreadMapBase
{
   //virtual functions
};

class QeueueThreadMap : public QueueThreadMapBase
{
   //your real implementation
};

class QeueueThreadMapTestStub : public QueueThreadMapBase
{
   //your test implementation
};

static QueueThreadMapBase* pGlobalInstance = new QeueueThreadMap;

QueueThreadMapBase* getInstance()
{
   return pGlobalInstance;
}

void setInstance(QueueThreadMapBase* pNew)
{
   pGlobalInstance = pNew
}

Then in your test just swap out the queue/thread map implementation. At the very least this exposes the singleton a little more.

like image 173
Snazzer Avatar answered Oct 16 '22 15:10

Snazzer


Some thoughts towards a solution:

Why do you need to enqueue notifications for observers that were created on a different thread? My preferred design would be to have the subject just notify the observers directly, and put the onus on the observers to implement themselves thread-safely, with the knowledge that Notified() might be called at any time from another thread. The observers know which parts of their state need to be protected with locks, and they can handle that better than the subject or the queue.

Assuming that you really have a good reason for keeping the queue, why not make it an instance? Just do queue = new Queue() somewhere in main, and then pass around that reference. There may only every be one, but you can still treat that as an instance and not a global static.

like image 31
JSBձոգչ Avatar answered Oct 16 '22 15:10

JSBձոգչ