×

Simple Share Buttons

SeanMcCammon C# .Net core 3 Software Developer

What Is The Difference Between A Singleton Class And Dependency Injection

What Is The Difference Between A Singleton Class And Dependency Injection

A singleton class is a design pattern where only one instance of a class can exist in a program at any given time. This means that every time an object is created from that class, it returns the same instance. Singleton classes are often used when we want to ensure that there is only one instance of a class in the application, such as a configuration class that should be used throughout the program.

On the other hand, Dependency Injection is a design pattern where the dependencies of an object are injected into it by an external entity, rather than the object creating them itself. In other words, instead of an object creating its own dependencies, it is provided with the dependencies from the outside. This makes the object more modular and testable since it can be easily replaced with a mock object for testing purposes.

Dependency Injection is often used in large-scale applications where the complexity of the code is high, and there is a need to reduce the coupling between different parts of the application. It also allows for greater flexibility in the application's design, making it easier to modify and extend.

In summary, the main difference between a Singleton class and Dependency Injection is that Singleton ensures that only one instance of a class exists in the program, while Dependency Injection is a way of providing an object with its dependencies from the outside. They can be used together, but they serve different purposes in software design.

What is a singleton class?

A Singleton class is a design pattern where only one instance of a class can exist in a program at any given time. This means that every time an object is created from that class, it returns the same instance.

Here is an example of a Singleton class in Java:

public class SingletonClass {      private static SingletonClass instance = null; // Private class variable to store the instance            // Private constructor to prevent instantiation of the class from outside      private SingletonClass() {          // Optional initialization code      }            // Public method to get the instance of the class      public static SingletonClass getInstance() {          if (instance == null) {              instance = new SingletonClass();          }          return instance;      }            // Public method to demonstrate the use of the class      public void sayHello() {          System.out.println("Hello, I am a Singleton Class!");      }  }

In this example, we define a class called SingletonClass with a private static class variable instance to store the instance of the class. The constructor method is made private to prevent instantiation of the class from outside. The getInstance method is used to get the instance of the class and creates one if it doesn't exist yet. The sayHello method is just a simple method to demonstrate the use of the class.

To use the Singleton class, we can call the getInstance method to get the instance of the class, and then use it to call the sayHello method, like this:

SingletonClass instance1 = SingletonClass.getInstance(); SingletonClass instance2 = SingletonClass.getInstance();  System.out.println(instance1 == instance2); // Output: true  instance1.sayHello(); // Output: Hello, I am a Singleton Class! instance2.sayHello(); // Output: Hello, I am a Singleton Class!

In this example, we create two instances of the SingletonClass using the getInstance method, but we only get one instance because the class is a Singleton. The sayHello method is called on both instances to demonstrate the use of the class.

What is a dependency injected class?

A Dependency Injected class is a class that has its dependencies injected from outside, rather than creating them internally. In other words, the dependencies are passed to the class from outside, rather than being created by the class itself. This allows for greater flexibility and modularity in the design of the software, as well as easier testing.

Dependency Injection is a design pattern where the dependencies of a class are passed to it through its constructor, methods or setters, instead of being created inside the class itself. This helps to decouple the class from its dependencies and makes it easier to replace or modify them without affecting the behavior of the class.

In a Dependency Injected class, the dependencies are often defined as interfaces or abstract classes, which allows for multiple implementations to be used interchangeably. This is known as Inversion of Control (IoC), where the control of the program's flow is shifted from the class itself to an external entity that manages the dependencies.

For example, consider a class Client that depends on a class Service. Instead of creating an instance of the Service class inside the Client class, the Service instance is passed to the Client constructor, like this:

public class Client {      private final Service service; // Dependency            // Constructor injection      public Client(Service service) {          this.service = service;      }            // Method to demonstrate the use of the class      public void doSomething() {          service.doSomething();      }  }

In this example, we define a class called Client that has a dependency on another class called Service. The Service class is not defined here but is assumed to exist. The dependency is injected through the constructor of the Client class. The doSomething method of the Client class calls a method of the Service class to demonstrate the use of the dependency.

To use the Client class, we need to create an instance of the Service class and pass it to the constructor of the Client class, like this:

Service service = new Service(); Client client = new Client(service);  client.doSomething();

In this example, we create an instance of the Service class and pass it to the constructor of the Client class. The doSomething method of the Client class is called to demonstrate the use of the dependency.

Dependency Injection allows for greater flexibility in the design of the software since the dependencies can be easily replaced with mock objects for testing purposes, and the code is less tightly coupled. This makes it easier to modify and extend the software over time.

In conclusion

Many would think or choose to give examples of a singleton and dependency injection to be similar, even the same using a singleton class as an example to explain dependency injection. However, we can see that they are two completely different patterns.

It's true that there is only ever one object of the type for each, but that is where the similarities end. 

Singleton pattern is used when we need to ensure that only one instance of a class is created throughout the application's lifecycle and that it is easily accessible by other parts of the application. Here are some scenarios where a Singleton pattern might be useful:

  1. Configuration settings: A Singleton class can be used to store application configuration settings that need to be accessed frequently from different parts of the application.
  2. Database connection: A Singleton class can be used to manage a single connection to a database, which can be shared across different parts of the application.
  3. Logging: A Singleton class can be used to manage application logging, which can be accessed from different parts of the application.
  4. Caching: A Singleton class can be used to manage a cache of frequently accessed data, which can be shared across different parts of the application.
  5. Thread pool: A Singleton class can be used to manage a pool of threads that can be reused across different parts of the application.

In general, the Singleton pattern is useful in situations where we need to ensure that there is only one instance of a particular class and that it is easily accessible by other parts of the application. However, it should be used judiciously, as overuse of the Singleton pattern can lead to a complex and inflexible design.

However, looking at the above list - dependency injected classes could also fit all of the above points. So, in a large complex system, it can be said that the dependency injection pattern should be used for modern systems and that a singleton pattern is not really required in today's system.

The other benefit of using dependency injection above a singleton is you can change the class injected. What I mean by that is, maybe you start with a logger class you like. You get most of what you need out of it. However, you find a new, better logger class that gives you more output. You can inject that new class without having to change much if any code. Where you do need to change any code it's very minimal.

That means less work to do when you make these types of changes, especially if it's over a large code base.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

linkedin facebook pinterest youtube rss twitter instagram facebook-blank rss-blank linkedin-blank pinterest youtube twitter instagram