I did this as an exercise just to practice/improve using generics.
Independent of how useful this implementation of a Singleton is, how is my coding in terms of using generics and any other aspect of class design of code style?
void Main()
{
var a = Singleton<MyClass>.Value;
var b = Singleton<MyClass, MyClassFactory>.Value;
var c = Singleton<MyClass>.Value;
var d = Singleton<MyClass, MyClassFactory>.Value;
var e = Singleton<MyOtherClass>.Value;
var f = Singleton<MyOtherClass>.Value;
var g = Singleton<MyOtherClass, MyOtherFactory>.Value;
var h = Singleton<MyOtherClass, MyOtherFactory>.Value;
}
class SingletonBase
{
protected static object Locker = new LockerObject();
}
class Singleton<T> : SingletonBase where T : new()
{
static T StaticT;
public static T Value
{
get
{
lock (Locker)
{
if(StaticT == null)
{
StaticT = Activator.CreateInstance<Factory<T>>().Create();
}
else
{
Console.WriteLine ("Singleton<T>::Value" + typeof(T).Name + " is already created");
}
}
return StaticT;
}
}
}
class Singleton<T, F> : SingletonBase where T : new() where F : IFactory<T>, new()
{
static T StaticT;
public static T Value
{
get
{
lock (Locker)
{
if(StaticT == null)
{
StaticT = new F().Create();
}
else
{
Console.WriteLine ("Singleton<T, F>::Value" + typeof(T).Name + " is already created");
}
}
return StaticT;
}
}
}
class LockerObject
{
Guid myGUID;
public LockerObject()
{
this.myGUID = Guid.NewGuid();
Console.WriteLine ("New LockerObject " + this.myGUID.ToString());
}
}
interface IFactory<T>
{
T Create();
}
class Factory<T> : IFactory<T> where T : new()
{
public T Create()
{
Console.WriteLine ("Factory<T>::Create()");
return new T();
}
}
class MyClassFactory : IFactory<MyClass>
{
public MyClass Create()
{
Console.WriteLine ("MyClassFactory::Create()");
return new MyClass();
}
}
class MyClass
{
public MyClass()
{
Console.WriteLine ("MyClass created");
}
}
class MyOtherClass
{
public MyOtherClass()
{
Console.WriteLine ("MyOtherClass created");
}
}
class MyOtherFactory : IFactory<MyOtherClass>
{
public MyOtherClass Create()
{
Console.WriteLine ("MyOtherFactory::Create()");
return new MyOtherClass();
}
}
Output:
New LockerObject 36aa2282-d745-43ca-84d2-998a78e39d51 Factory<T>::Create() MyClass created MyClassFactory::Create() MyClass created Singleton<T>::ValueMyClass is already created Singleton<T, F>::ValueMyClass is already created
T
is required to have a public parameterless constructor, anyone can create a new instance of it. Same problem with the version usingIFactory<T>
. – w0lf May 23 '12 at 7:47