Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to abstract a singleton class?

This is how I write my singleton classes.

public class MyClass {     /// <summary>     /// Singleton     /// </summary>     private static MyClass instance;      /// <summary>     /// Singleton access.     /// </summary>     public static MyClass Instance     {         get         {             if (_instance == null)             {                 _instance = new MyClass();             }             return _instance;         }     }      private MyClass() { .... } } 

How To Create A Singleton Pattern That Is Reusable?

Singleton patterns present the following challenges.

  • The constructor is private or protected.
  • A base class can't instantiate an inherited class. So you can reuse a common abstract MyAbstractSingletonClass.
  • It has to have a local read-only property to get the instance.

The Problem

I'm using this pattern on a number of classes and always have to write the same code. How can I write something that is reused whenever I need a singleton?

like image 692
Reactgular Avatar asked May 25 '13 01:05

Reactgular


People also ask

Can a singleton class be abstract?

The Singleton pattern requires a private constructor and this already makes subclassing impossible. You'll need to rethink your design. The Abstract Factory pattern may be more suitable for the particular purpose. The purpose of the private constructor in the Singleton is to prevent anyone else instantiating it.

How many ways can you break a singleton class in Java?

There are mainly three concepts in which we can break the singleton property of a Singleton class in Java. In this post, we will discuss how it can break and how to prevent it. Here is sample Singleton class and SingletonTest class.

How do you handle a class singleton?

Remember the key points while defining class as a singleton class that is while designing a singleton class: Make a constructor private. Write a static method that has the return type object of this singleton class. Here, the concept of Lazy initialization is used to write this static method.

How do you destroy a singleton object in Java?

If you really need to reset a singleton instance (which doesn't makes much sense actually) you could wrap all its inner members in a private object, and reinitialize via an explicit initialize() and reset() methods. That way, you can preserve your singleton istance and provide some kind of "reset" functionality.


2 Answers

You can achieve this using a combination of a self-referencing generic type constraint, and a "new()" type constraint.

The "new" constraint ensures that any child class will always have a parameterless constructor, so _instance = new T(); will always work.

The self-referencing type constraint ensures that the "Instance" static property always returns the correct Type; not the "base" type. Your singleton base class would look something like this:

public abstract class SingletonBase<T>      where T : SingletonBase<T>, new() {     private static T _instance = new T();     public static T Instance     {         get         {                             return _instance;         }        } } 

Your child classes will look like this:

public class MyChildSingleton : SingletonBase<MyChildSingleton> {     //Done! } 

Of course, if you want your singleton to be general-purpose, you should also change your "create singleton instance" code slightly, to use the "double-check lock" pattern, or the Lazy class, to make it thread-safe.

The big caveat: if you use this method, the "new()" constraint pretty much ensures that your class will always have a public, parameterless constructor. That means your end-users could always just call new MyChildSingleton() if they really wanted, bypassing your singleton instance entirely. Your singleton would be "by convention," instead of strictly enforced. To get around this would take a bit more engineering. In the above scenario, the convention seems to be that you should name your static instance "Default" instead of "Instance." This subtly conveys the fact that your class offers a 'suggested' singleton instance, but using it is technically optional.

I've made some attempts to strictly enforce the singleton pattern, and the end result was to use reflection to manually invoke a private constructor. You can see my full code attempt here.

like image 163
BTownTKD Avatar answered Sep 25 '22 13:09

BTownTKD


The true solution is starting with BTownTKD's approach but augmenting it with the Activator.CreateInstance method which allows your child classes to keep the private constructors.

Parent Class

public abstract class SingletonBase<T> where T : SingletonBase<T> {     private static readonly Lazy<T> Lazy =         new Lazy<T>(() => Activator.CreateInstance(typeof(T), true) as T);      public static T Instance => Lazy.Value; } 

Child Class

public sealed class MySingleton : SingletonBase<MySingleton> {     private MySingleton() { } } 

Full Implementation Example Here

like image 40
Buvy Avatar answered Sep 26 '22 13:09

Buvy