Your resource for web content, online publishing
and the distribution of digital products.
S M T W T F S
 
 
 
 
 
1
 
2
 
3
 
4
 
5
 
6
 
7
 
8
 
9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
 
30
 

Refactoring 018 - How to Replace a Singleton

Tags: testing
DATE POSTED:November 5, 2024

Breaking Free from the Evil Singleton

TL;DR: Refactor singletons to reduce coupling

Problems Addressed Related Code Smells

https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-vii-8dk31x0?embedable=true

https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-v-evj3zs9?embedable=true

https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-v-evj3zs9?embedable=true

Steps
  1. Identify the singleton
  2. Locate all references to its getInstance() method
  3. Refactor the singleton to a standard class
  4. Inject it as a dependency
Sample Code Before public class DatabaseConnection { private static DatabaseConnection instance; private DatabaseConnection() {} public static DatabaseConnection getInstance() { if (instance == null) { instance = new DatabaseConnection(); } return instance; } public void connect() { } } public class Service { public void performTask() { DatabaseConnection connection = DatabaseConnection.getInstance(); connection.connect(); } } After public class DatabaseConnection { // 1. Identify the singleton public void connect() { } } public class Service { // 2. Locate all references to its getInstance() method. private DatabaseConnection connection; // 3. Refactor the singleton to a standard class. public Service(DatabaseConnection connection) { // 4. Inject it as a dependency. this.connection = connection; } public void performTask() { connection.connect(); } } DatabaseConnection connection = new DatabaseConnection(); // You can also mock the connection in your tests Service service = new Service(connection); service.performTask(); Type
  • [x] Semi-Automatic
Safety

This refactoring is safe when you update all references to the singleton and handle its dependencies correctly.

\ Testing each step ensures that no references to the singleton are missed.

Why Is the Code Better?

Refactoring away from a singleton makes the code more modular, testable, and less prone to issues caused by the global state.

Injecting dependencies allows you to easily replace DatabaseConnection with a mock or different implementation in testing and other contexts.

Tags
  • Coupling
Related Refactorings

https://maximilianocontieri.com/refactoring-007-extract-class?embedable=true

See also

https://hackernoon.com/singleton-pattern-the-root-of-all-evil-e4r3up7?embedable=true

https://hackernoon.com/coupling-the-one-and-only-software-designing-problem-9z5a321h?embedable=true

Credits

Image by PublicDomainPictures from Pixabay

This article is part of the Refactoring Series.

How to Improve Your Code With Easy Refactorings

Tags: testing