As a software engineer, when you work for some time and get some experience with Object-Oriented Programming (OOP), you will have some realization, like:
You will find a pattern while solving similar problems in several projects, or even different places of the same project. As you gain more experience and become familiar with more solutions, it becomes easier for you, as solutions for similar problems will follow similar patterns.
You not only want to implement changes for your current task/requirement but also want to write code in such a way that it can accommodate future changes with just small to no changes in the future. So flexibility becomes important.
To achieve a good design in software engineering using Object-Oriented Programming(OOP), we rely on design patterns.
Let’s take a look at what are design patterns and what design patterns are not.
What Design Patterns are not?
- Design patterns are not full implementations of any feature or requirement.
- Solutions are not domain specific. These patterns are general and can be implemented for any business.
- Problems related & specific to distributed systems, real-time applications, or concurrency-related issues are not handled.
- Design patterns do not represent any specific data structures or algorithms.
What are Design Patterns?
- Solutions to common/general problems while designing software.
- Each design pattern has a clear use case, proper implementation guidelines, and the reason for choosing that approach.
- Recognized from experience and defined by experts.
- Solutions are specifically for Object-Oriented Programming.
- Each pattern has a defined use case, a well-defined solution(with all components in detail), and consequences.
- Design patterns work as a template to solve common design patterns. The implementation guidelines are clear but not restricted. So the implementation in your use case may vary a little bit, but the approach to the solution will remain standard.
Elements of Design Pattern
Each design pattern has 4 essential elements, and these elements need to be clearly defined for a pattern. Let’s take a look at those elements:
- Name: naming a design pattern is important, as the name will give you some idea as soon as you read the name, and might also give you some idea about how the implementation is going to be. Also having a name help while discussing the design patterns, you can just mention the name to another software engineer (who has an understanding of Design Pattern) and that engineer will immediately know what you are saying. So the discussion about the approach and solutions becomes easier.
- Problem/Use-Case: the problem area or the use case need to be clearly mentioned, for using a design pattern.
- Solution: the steps of the implementation are clearly defined. The relation among the parts of the implementation and how they communicate is also defined.
- Consequences: effect of the pattern implementation can be mentioned. As the effect can not always be determined fully, and it varies depending on the specific use case and implementation. So the consequences can not be fully determined while discussing design patterns.
Types of Design Patterns
Design patterns are divided into 3 categories, based on their working pattern.
Each category of Design Patterns contains multiple patterns.
Scope of Design Pattern
As design patterns are implemented for Object-Oriented design, so there can be 2 scopes for a design pattern:
- Class: patterns that have class scope handle relations between classes & subclasses, and these relations are fixed at compile time.
- Object: patterns that have object scope deals with the relationship between objects, and these relations can be changed at runtime.
Following Diagram shows the categories and scopes of the design patterns.
Let’s take a look at each type and what patterns are included in each of these.
Creational patterns provide a way to create objects. While creating an object, these patterns are used to wrap the instantiation process of that new object.
Here are some criteria for creation patterns:
- The different creational process does the object creation differently and is used in different use cases.
- The creation of a new object is abstracted and hidden inside the creational pattern implementation, so the client does not need to know the details while using it.
- Sometimes the creational patterns can be interchangeable. Like, in some use cases, the Abstract Factory and Prototype patterns can be used interchangeably.
- Sometimes these patterns can be complementary. Like, the Prototype pattern can use Singleton in the implementation, or the Builder can use another pattern while building elements.
Here is the list of creational patterns. Check the details and implementation in different programming languages, below.
Strctural patterns are used to compose/construct a bigger structure by using classes and objects. While building the structure, the patterns ensure flexibility and extensibility.
Here is the list of structural patterns. Check the details and implementation in different programming languages, below.
Behavioral patterns deal with the communication between a group of objects or classes. By impacting communication between objects, these patterns increase the flexibility of implementation.
Class-scoped patterns use inheritance to distribute responsibility between classes.
On the other hand, Object-scoped patterns use composition instead of inheritance.
Here is the list of behavioral patterns.