Quick View of Design Patterns from GOF Book
The best designers use many design patterns
Design Pattern
Design patterns are general, reusable solutions to solve common problems in software design. Each pattern is like a blueprint that you can customize to solve a specific problem in your code.
Categories of Design?Patterns
In GoF (Gang of Four) we have 3 categories of Design Patterns
1. Creational Patterns
These patterns provide a way to create objects while hiding the creation logic rather than instantiating objects. ex: encapsulation.
In simple words, these patterns provide various object creation mechanisms, which increase flexibility and reuse of existing code.
This design pattern lets you ensure that a class has only one instance while providing a global access point to this instance. It solves two problems at a time, violating the Single Responsibility Principle.
Singleton’s implementation has two things in common:
This pattern lets you copy existing objects without making your code dependent on their classes.
The Prototype pattern delegates the cloning process to the actual objects that are being cloned. The pattern declares a common interface for all objects that support cloning. This interface lets you clone an object without coupling your code to the class of that object.
The implementation of the clone method is very similar in all classes. The method creates an object of the current class and carries over all the field values of the old object into the new one. You can even copy private fields because most programming languages let objects access the private fields of other objects that belong to the same class.
This pattern is used when the creation of an object directly is costly. ex: An object is to be created after a costly database operation. We can cache the object, return its clone on the next request, and update the database as and when needed thus reducing database calls.
This pattern lets you construct complex objects step by step. This pattern allows you to produce different types and representations of an object using the same construction code.
The Builder pattern suggests that you extract the object construction code out of its own class and move it to separate objects called builders.
This pattern deals with the problem of creating objects without having to specify the exact class of the object that will be created. This is done by creating objects by calling a factory method.
It provides an interface for creating objects in a base class but allows sub-classes to alter the type of objects that will be created.
Either specified in an interface and implemented by sub-classes or implemented in a base class and optionally overridden by derived classes, rather than by calling a constructor.
This pattern lets you produce families of related objects without specifying their concrete classes.
It works around a super-factory which creates other factories. This factory is also called a factory of factories.
2. Structural Patterns
Structural patterns are concerned with how classes and objects are composed to form larger structures. Structural class patterns use inheritance to compose interfaces or implementations
This pattern is used when we need to treat a group of objects in a similar way as a single object. Composite pattern composes objects in terms of a tree structure to represent part as well as a whole hierarchy.
In simple words, this pattern creates a class that contains a group of its own objects. This class provides ways to modify its group of the same objects.
This design pattern works as a bridge between two incompatible interfaces. This type of design pattern comes under a structural pattern as this pattern combines the capability of two independent interfaces.
You can create an adapter. This is a special object that converts the interface of one object so that another object can understand it.
An adapter wraps one of the objects to hide the complexity of conversion happening behind the scenes. The wrapped object isn’t even aware of the adapter.
This design pattern lets you split a large class or a set of closely related classes into two separate hierarchies; abstraction and implementation, which can be developed independently of each other.
This pattern is used when we need to decouple an abstraction from its implementation so that the two can vary independently. This type of design pattern comes under structural pattern as this pattern decouples implementation class and abstract class by providing a bridge structure between them.
This design pattern allows a user to add new functionality to an existing object without altering its structure. This type of design pattern comes under a structural pattern as this pattern acts as a wrapper to the existing class.
This pattern creates a decorator class that wraps the original class and provides additional functionality keeping the class methods signature intact.
In simple words, this pattern lets you attach new behaviors to objects by placing these objects inside special wrapper objects that contain the behaviors.
This pattern provides a simplified interface to a library, a framework, or any other complex set of classes.
It hides the complexities of the system and provides an interface to the client using which the client can access the system. This type of design pattern comes under a structural pattern as this pattern adds an interface to the existing system to hide its complexities.
This design pattern lets you provide a substitute or placeholder for another object. A proxy controls access to the original object, allowing you to perform something either before or after the request gets through to the original object.
In this pattern, a class represents the functionality of another class. This type of design pattern comes under a structural pattern.
The flyweight pattern is primarily used to reduce the number of objects created decrease memory footprint and increase performance. This type of design pattern comes under structural pattern as this pattern provides ways to decrease object count thus improving the object structure of the application.
In simple words, this pattern lets you fit more objects into the available amount of RAM by sharing common parts of the state between multiple objects instead of keeping all of the data in each object.
This pattern also suggests that you stop storing the extrinsic state inside the object. Instead, you should pass this state to specific methods which rely on it. Only the intrinsic state stays within the object, letting you reuse it in different contexts. As a result, you’d need fewer of these objects since they only differ in the intrinsic state, which has much fewer variations than the extrinsic.
3. Behavioral Patterns
In these design patterns, identify common communication patterns between objects and realize these patterns. These patterns are also concerned with algorithms and the assignment of responsibilities between objects.
This pattern lets you traverse elements of a collection without exposing its underlying representation. ex: list, stack, tree, etc.
The main idea of the Iterator pattern is to extract the traversal behavior of a collection into a separate object called an iterator.
In this pattern, we create objects which represent various states and a context object whose behavior varies as its state object changes. This type of design pattern comes under a behavior pattern.
This pattern is a data-driven design pattern and falls under the behavioral pattern category. A request is wrapped under an object as a command and passed to the invoker object.
Invoker object looks for the appropriate object that can handle this command and passes the command to the corresponding object that executes the command.
As the name suggests, the chain of responsibility pattern creates a chain of receiver objects for a request. This pattern decouples the sender and receiver of a request based on the type of request.
Upon receiving a request, each handler decides either to process the request or to pass it to the next handler in the chain.
In this pattern, normally each receiver contains a reference to another receiver. If one object cannot handle the request then it passes the same to the next receiver and so on.
In this design pattern, an abstract class exposes defined way(s)/template(s) to execute its methods. Its subclasses can override the method implementation as per need but the invocation is to be in the same way as defined by an abstract class.
defines the skeleton of an algorithm in the parent class but lets child classes override specific steps of the algorithm without changing its structure.
This design pattern is used when there is a one-to-many relationship between objects such as if one object is modified, its dependent objects are to be notified automatically.
In simple words lets you define a subscription mechanism to notify multiple objects about any events that happen to the object they are observing.
In this pattern, a class behavior or its algorithm can be changed at run time.
We create objects that represent various strategies and a context object whose behavior varies as per its strategy object.
The strategy object changes the executing algorithm of the context object.
Cheers!