Singleton Pattern

Use Case: When you need the same state (instance of a class) shared in across your application. Example configuration data that is more expensive to continually load. A Database repository (Data access), Object factory (creates instance of components)

Warning: Only use this when you really need it, potentially you could be using up a lot of memory if you do this when not needed. Think of a Web Server that is not restarted that often with 100/1000s of singleton classes using up memory unnecessarily.

Erich Gamma: When discussing which patterns to drop, we found that we still love them all. (Not really - Im in favor of dropping Singleton. Its use is almost always a design smell) ~ post original publication when the authors met to discuss the orginal patterns.

Motivation & Definition

You would use a Singleton when the constructor call is particularly expensive and you only really want that constructor call being done once.

The singleton pattern ensures that only one object of a particular class is ever created. (so a single instance exists) All further references to objects of the singleton class refer to the same underlying instance.

This instance is what would have been created in the initial (and only) constructor call and ideally have lazy instantiation.

Example Code

The complete code example can be seen at https://github.com/carlpaton/SingletonPatternDemo.

These are based on the work by Tim Corey and Dmitri Nesteruk.

Dependency Injection

Warning: This example doesnt prevent consumers creating additional copies so would rely on code review.

These classes can be injected using built in Dependency Injection in .Net when calling ConfigureServices and passing it a services collection.

1
services.AddSingleton<TableServers>

Here .Net will inject TableServers as a singleton for you \ :D /

This is however not using the singleton design pattern - this is just using .Net to manage the class for you as if it WAS a singleton.

The TableServers code be defined as

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/// <summary>
/// Represents a restaurant with waiters and waitresses ready to be assigned to serve tables of hungry customers.
/// It will be done via a rotating list so everybody gets a turn.
/// </summary>
public class TableServers
{
private List<string> _servers = new List<string>();
private int _next = 0;

public TableServers()
{
_servers.Add("Foo");
_servers.Add("Bar");
_servers.Add("Baz");
_servers.Add("Bat");
}

public string GetNext()
{
var next = _servers[_next];
_next++;

if (_next >= _servers.Count)
{
_next = 0;
}

return next;
}
}

When calling TableServers -> GetNext()

1
2
3
4
5
6
7
var host = new TableServers();

for (int i = 0; i < 10; i++)
{
Console.WriteLine($"The next server is: {host.GetNext()}");
}

Expected output is:

1
2
3
4
5
6
7
8
9
10
The next server is: Foo
The next server is: Bar
The next server is: Baz
The next server is: Bat
The next server is: Foo
The next server is: Bar
The next server is: Baz
The next server is: Bat
The next server is: Foo
The next server is: Bar

Table Servers (Tim Corey)

Here the instantiation can only be done using GetTableServers() so the class TableServersSingleton maintains its own state.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
{
/// <summary>
/// Represents a restaurant with waiters and waitresses ready to be assigned to serve tables of hungry customers.
/// It will be done via a rotating list so everybody gets a turn.
/// </summary>
public class TableServersSingleton
{
/// <summary>
/// readonly - important as it means we cannot overwrite this `instance`
/// static - important as we dont have to instanciate the class (we cannot actually as the ctor is private)
/// </summary>
private static readonly TableServersSingleton _instance = new TableServersSingleton();

private List<string> _servers = new List<string>();
private int _next = 0;

private TableServersSingleton()
{
_servers.Add("Foo");
_servers.Add("Bar");
_servers.Add("Baz");
_servers.Add("Bat");
}

/// <summary>
/// The only way to instanciate this class is now through this method, so the internal state is never changed
/// </summary>
/// <returns></returns>
public static TableServersSingleton GetTableServers() => _instance;

public string GetNext()
{
var next = _servers[_next];
_next++;

if (_next >= _servers.Count)
{
_next = 0;
}

return next;
}
}

If you then create some instances and run the code the the result will repeat Foo, Bar, Baz and Bat. This means the class is thread safe as it will rotate through the list correctly.

1
2
3
4
5
6
7
8
var host1 = TableServersSingleton.GetTableServers();
var host2 = TableServersSingleton.GetTableServers();

for (int i = 0; i < 5; i++)
{
Console.WriteLine($"The next server is: {host1.GetNext()}");
Console.WriteLine($"The next server is: {host2.GetNext()}");
}

Expected output. This is the same as calling TableServers -> GetNext() from a none singleton type class.

1
2
3
4
5
6
7
8
9
10
The next server is: Foo
The next server is: Bar
The next server is: Baz
The next server is: Bat
The next server is: Foo
The next server is: Bar
The next server is: Baz
The next server is: Bat
The next server is: Foo
The next server is: Bar

Singleton Database (Dmitri Nesteruk)

WIP!

References