Home > .Net, Design > Simple singleton pattern with inheritance in C#.NET (part 1)

Simple singleton pattern with inheritance in C#.NET (part 1)

Singleton is very simple and widely used Design Pattern. This pattern is described in a lot of blogs, articles and books (e.g. GoF = Gang of Four). According to GoF,  singleton’s job is to “Ensure a class has one instance, and provide a global point of access to it”. In a general case, singleton can be extended, in order to ensure a class has n instances, while 1 ≤ n < ∞.

How can one build a singleton?

Two steps to make some class to be a singleton:
1) Forbid straightforword creation => let constructor be private (or protected in some cases).
2) Provide general access point => static property (or function), which allows an access to object.

Let’s see the code:

class Keyboard
{
	private static Keyboard m_instance;
 
	private Keyboard() {}

	public static Instance
	{
		get
		{
			if (m_instance == null)
				m_instance = new Keyboard();

			return m_instance;
		}
	}
}

Note, that this simple implementation is not thread-safe. There are several ways to make a singleton thread-safe; hopefully I will show them in other post.

This singleton implementation has a some advantage: lazy initialization. Until “Instance” property is called first time, there is no allocation of a real instance. If there was no call, the allocation will not take place at all. If the instance is “heavy”, that’s good. On the other hand, if the singleton allocates many native memory, then the postpond allocation could happen, when the native memory is very fragmented, and could simply fail. Same thing can happen, if the singleton is very big and is allocated in a Large Objects Heap. Such a tradeoff.

Now, assume we need to create some extendable framework. Base classes used inside can be extended using inheritance (suppose they was built properly) and registered inside some factory. But what should we do, if the base class is singleton? Singletoness can not be inherited… and neither static property/function…

Well, first thing, I would check, whether the base class really have to be singleton. Many time people make overuse of this pattern, just because it is easy. This point could be a subject of another post. Suppose, we really really want this singleton in our infrastructure. Now I’ll show, how can we create inheretable singleton:

abstract class Keyboard<DerivedType>
	where DerivedType : new()
{
	private static DerivedType m_instance;
 
	public static DerivedType Instance
	{
		get
		{
			if (m_instance == null)
				m_instance = new DerivedType();

			return m_instance;
		}
	}

	abstract public void Connect();
}

class USBKeyboard : Keyboard<USBKeyboard>
{
	override public void Connect()
	{
	}
}

Great! We can use the Keyboard class within the framework and user will inherit it in a presented way. But…
can you see a “little” problem? USBKeyboard has public constructor! It can be created directly! We can prevent this disaster it in either classic or reflection way. I’ll show them both:

1) Classic way: we will do run-time check of the state, and will throw exception if the state is unappropriate:

abstract class Keyboard<DerivedType>
	where DerivedType : new()
{
	private static DerivedType m_instance;
	private static bool m_singletonCreation;

	public static DerivedType Instance
	{
		get
		{
			if (m_instance == null)
			{
				m_singletonCreation = true;
				m_instance = new DerivedType();
				m_singletonCreation = false;
			}
			return m_instance;
		}
	}

	protected void ValidateSingletonCreation()
	{
		if (!m_singletonCreation)
			throw new ApplicationException("Singleton must not be created.");
	}

	abstract public void Connect();
}

class USBKeyboard : Keyboard<USBKeyboard>
{
	public USBKeyboard()
	{
		ValidateSingletonCreation(); // throws exception if called
	}

	override public void Connect()
	{
	}
}

2) .NET reflection:we will use C#.NET “Activator”. The “Activator” allows object construction, even if the constructor is private:

abstract class Keyboard<DerivedType>
{
	private static DerivedType m_instance;

	public static DerivedType Instance
	{
		get
		{
			if (m_instance == null)
			{
				m_instance = (DerivedType)Activator.CreateInstance(
					typeof(DerivedType), true);
			}
			return m_instance;
		}
	}

	abstract public void Connect();
}

class USBKeyboard : Keyboard<USBKeyboard>
{
	private USBKeyboard()
	{
	}

	override public void Connect()
	{
	}
}

That’s all. One can choose any implementation. Remember: that is not an attempt to create a singleton for all scenarios in a life. The target was using a singleton inside some framework with an option to extend is in program’s “knowledge level”. This target is achieved.
Still, those singletones are not thread-safe. This we will make next time in part 2

Categories: .Net, Design Tags: , , ,
  1. No comments yet.
  1. No trackbacks yet.