Table of contents
why understanding design patterns is important
In the vast landscape of software engineering, design patterns act as guiding stars that illuminate our path towards building intelligent and robust software systems. These patterns are tried and tested knowledge, solutions for the recurring problems from the expert experienced developers.
Understanding design patterns is not just essential; it is a gateway to unlocking the true potential of intelligent software engineering.
Below are the important points on why it's important to understand and use design patterns in software development.
1. Speaking the Same Language
Design patterns are like a common language spoken by developers around the world. When we understand and use design patterns, we can easily communicate ideas and solutions with other developers.
2. Making Software Easy to Maintain
Maintaining software can be challenging, especially as it grows and evolves. Design patterns play a crucial role in making software easier to maintain. They provide a clear and well-documented structure that makes it easier to understand, debug, and modify code. This saves time and effort, making software maintenance less of a headache.
3. Promoting Reusability and Extensibility
Design patterns promote reusability and extensibility, two cornerstones of intelligent software engineering. By encapsulating proven design solutions, patterns provide a solid foundation for building reusable components. They enable us to extract common functionality and structure it in a modular and scalable manner.
Important types of the design patterns
Based on this purpose there are three important types of the design patterns
Creational design patterns
Structural design patterns
behavioral design patterns
Creational design pattern concerns the process of object creation.
Structural design patterns deal with the composition of classes and objects to form larger structures, emphasizing relationships between entities.
Behavioral design patterns focus on communication and interaction between objects, defining how they collaborate and distribute responsibilities.
1) creational design patterns
Creational design pattern gives you a lot of flexibility in what gets created, who creates it and how it gets created and when.
Two types of creational patterns
Creational class patterns -
Creational object patterns -
Creational class patterns defer some part of object creation to subclasses, while creational object patterns defer it to another object.
Factory method pattern.
one liner :"Let subclasses decide which objects to create."
Factory method pattern is all about providing the ability to the client class to instantiate an object without worrying about how it’s instantiated, managed and destroyed. The client class has to only request the object and not worry about how it’s been created.
Factory method pattern defines an interface for creating an object but lets the subclass decide which class to instantiate.
org.springframework.beans.factory.BeanFactory in spring framework is implemented using the factory method pattern which is responsible for creating, managing, caching, and wires the application objects.
JdbcTemplate and RestTemplate also uses the factory method pattern.
One Liner :
"Only one instance to rule them all."
The singleton pattern ensures a class has only one instance, and it provides a global point of access to it.
example code and further reference : https://ecommercearchitect.hashnode.dev/singleton-pattern-java-explained
prototype design pattern.
one liner :
"Clone and customize, a blueprint in action."
This pattern offers a more elegant and flexible alternative to copy-paste.
With the Prototype pattern, you can create new objects by cloning existing ones, saving time and reducing the potential for errors.
The Prototype design pattern allows us to create new objects by cloning existing ones, rather than by creating them from scratch.
The intent of the Prototype pattern is to specify the kinds of objects to create using a prototypical instance, and create new objects by copying this prototype.
example code and further reference : https://ecommercearchitect.hashnode.dev/prototype-pattern-java-explained
one liner :
"Step by step, build it right."
The intent behind the Builder Design Pattern is to separate the construction of a complex object from its representation so that the same construction process can create different representations.
example code and further reference : https://ecommercearchitect.hashnode.dev/builder-design-pattern-java-explained
2) structural design patterns
Structural patterns are concerned with how classes and objects are composed to form large structures.
Structural class patterns focus on the relationship between classes and how they can be organized to form larger structures or functionalities. They primarily deal with class inheritance and composition to achieve system design and reusability.
Structural object patterns focus on the composition of objects to form larger structures or functionalities. They aim to establish relationships and interactions between objects, emphasizing object composition and collaboration.
Adaptor design pattern
one liner :
Bridging the gap between incompatible interfaces, making them work together seamlessly.
Adaptor pattern converts the interface of a class into another interface clients expect. The adapter lets classes work together that couldn't otherwise because of incompatible interfaces. This is done simply by adapter implementing the interface of one object and wrapping another object. That is, implements the interface of a client class and associate adaptee class and then uses this adaptee object to invoke methods on the adaptee class.
example code and further reference: https://www.adityatechinsights.com/adapter-design-pattern-java-explained
Composite design pattern
Treating individual and group objects uniformly, forming a unified structure with hierarchical relationships.
It’s about composing different objects of a similar family (interface) and then appearing them as one for an external client. Each object in the composition may or may not have child objects.
The Composite Design Pattern allows you to compose objects into tree structures and then work with these structures as if they were individual objects.
example code and further reference: https://www.adityatechinsights.com/composite-design-pattern-java-explained
Decorator design pattern
Adding new functionalities dynamically, enhancing an object's behavior without altering its core implementation.
In simple words, the decorator pattern helps attach different behaviours to the object at the runtime by wrapping the object with a specific type of wrapper class which contains the new behavior logic.
The Decorator Pattern attaches additional responsibilities to an object dynamically. Decorator provides a flexible alternative to subclassing for extending functionality.
example code and further reference: https://www.adityatechinsights.com/decorator-pattern-java-explained
Proxy design pattern
Acting as a representative or surrogate for another object, controlling access and providing additional functionality when needed.
The intent of the proxy design pattern is to Provide a surrogate or placeholder for another object to control access to it. This is also called a “surrogate”.
Think of a proxy pattern when you want to add an extra layer of indirection to access a resource or control access to it. It is useful in scenarios where you would want to improve performance by caching frequently used objects, reduce network traffic by implementing lazy loading, or provide a simplified interface to a complex system.
example code and further reference: https://www.adityatechinsights.com/proxy-design-pattern-java-explained
3) Behavioural design patterns
Behavioral design patterns intent to focus on communication and interaction between objects, defining how they collaborate and distribute responsibilities.
Use: These patterns are used to manage complex object interactions, providing flexible communication patterns.
Behavioral patterns are useful when you want to decouple sender and receiver objects, observe changes in objects, or define algorithms that can be changed at runtime.
Template method design pattern
Follow the blueprint, customize the details.
The main intent behind the template method pattern is to provide the skeleton of an algorithm in the parent class and let subclasses extend the parent and define fill-ins by overriding methods. Well, the interesting part is that though algorithm fill-ins are implemented in the subclasses they are called by the parent class. Only parent calls those methods from subclass and this is called as famous “ Don’t call us, we will call you” Principle.
This is the type of behavioural design pattern where inheritance is used to describe algorithm and flow of control. Superclass defines the default and abstract methods and lets subclass provide an implementation of abstract methods.
example code and further reference: https://www.adityatechinsights.com/template-method-pattern-java-explained
Strategy design pattern
Switch it up, choose the best approach.
All intent behind the strategy pattern is to encapsulate behaviors that belongs to a similar purpose and make them interchangeable . Behaviors are methods in OO design and here encapsulation means creating different strategy classes which have dedicated logic that can be interchanged by other logic (even on runtime) to solve a similar category purpose.
When you have a situation where you have to write different methods which belong to a similar cause but each of those has different logic to solve that problem then think about using a strategy pattern.
example code and further reference: https://www.adityatechinsights.com/strategy-pattern-java-explained
Command design pattern
Wrap it up, encapsulate actions for future execution.
The Command Design Pattern is all about encapsulating a request as an object and passing it as a request parameter. It decouples the object that invokes the action from the object that performs the action.
example code and further reference: https://www.adityatechinsights.com/command-pattern-java-explained
Observer design pattern
Stay in sync, get notified when things change.
The basic idea behind observer pattern is to have a publisher — subscriber like mechanism , where publisher wants to notify multiple subscriber objects regarding some events / state change which is the in interest of subscriber.
The observer pattern defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.
example code and further reference: https://www.adityatechinsights.com/observer-pattern-java-explained
Iterator design pattern
Take it step by step, explore a collection one element at a time.
Iterator pattern is all about streamline the access of the collection so that the client which want to iterate over collection must not worry about entire collection instead it just check if list hasNext() element and call next() element.
Provides a way to access the elements of an aggregate object sequentially without exposing its underlying representation.
example code and further reference: https://www.adityatechinsights.com/iterator-design-pattern-java-explained
Understanding design patterns is crucial in software engineering as they provide tried and tested solutions to recurring problems. Design patterns act as a common language among developers, facilitating effective communication and collaboration. They also make software maintenance easier by providing well-documented structures and promoting reusability and extensibility. There are three main types of design patterns: creational, structural, and behavioral. Creational patterns focus on object creation, structural patterns deal with class and object composition, and behavioral patterns manage object interactions and responsibilities.