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 | /// <summary> |
When calling TableServers -> GetNext()
1 | var host = new TableServers(); |
Expected output is:
1 | The next server is: Foo |
Table Servers (Tim Corey)
Here the instantiation can only be done using GetTableServers()
so the class TableServersSingleton
maintains its own state.
1 | { |
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 | var host1 = TableServersSingleton.GetTableServers(); |
Expected output. This is the same as calling TableServers -> GetNext()
from a none singleton type class.
1 | The next server is: Foo |
Singleton Database (Dmitri Nesteruk)
WIP!