Let’s get started!
What are design patterns?
- They are widely applicable. You can solve a multitude of common problems with the generic templates that they provide.
- They are reusable. Other developers can easily build upon a design pattern. Since they aren’t tied to a specific problem, they can be reused throughout your code.
- They solve problems elegantly. Design patterns reduce the size of a codebase through optimized solutions.
- They are proven solutions. The results are reliable and efficient. That is because they are derived from the best practices of other experienced developers. You can be certain they’ll work when implemented.
- They eradicate the need to refactor code. Design patterns are the most tested, optimal solution for a given problem, so it’s unlikely that you’ll need to refactor the code.
1. Command design patterns
The command pattern allows encapsulation of the requests or operations into separate objects. It decouples the objects that send requests from the objects responsible for executing those requests. This makes it easy to pass method calls and issue commands that delegate responsibility to other objects. You can use it to:
- Queue and execute requests at different times
- Perform operations such as reset or undo
- Keep a history of requests
Consider an example: a client is directly accessing the methods of an API throughout an application. Well, what happens when the implementation of that API changes? We could make use of abstraction to separate the requesting objects from those implementing the request. Now, if a change occurs, only the object making the call will need to change. The essence of the command pattern includes the following components.
- Invoker: asks the command to carry out the request
- Command: has information about the action and binds it to the receiver by invoking the corresponding operation
- Receiver: knows how to perform the operations associated with the command
- Client: creates a command and sets the receiver who’ll receive the command
2. Observer design pattern
The observer design pattern is useful for places where objects communicate with other objects. For example, there are many situations where one component of your code changes, so another component needs an update. The observer pattern communicates with dependent objects to do just that . In this behavioral pattern, the modules only modify the current state of data. An example of this is the MVC architecture: as one component changes, the other updates.
When working with this pattern, we need to distinguish between independent and interdependent objects. This pattern allows objects (called observers) that have subscribed to an event to wait for input and react to it when notified. The main subject maintains a list of all the observers. When the event occurs, it notifies the observers to update.
The observer pattern is used when we need to:
- Improve code management by breaking down large applications into loosely-coupled objects
- Provide greater flexibility by enabling a dynamic relationship between observers and subscribers
- Improve communication between different parts of the application
- Create a one-to-many dependency between objects that are loosely coupled
The constructor also defines the subscribe and unsubscribe functions to register or remove an observer from the subscription. We also define the Observer class with an update function that is invoked by the Subject to notify the observer.
3. Singleton Pattern
The singleton pattern is a type of creational pattern that restricts the instantiation of a class to a single object. A class can create an instance of the class the first time it is instantiated, but on the next try, the existing instance of the class is returned. The singleton pattern is used mostly when you want a single object to coordinate actions across a system.
Singletons are mostly used by:
- Services: services can be singleton since they store the state, configuration, and provide access to resources. Therefore, it makes sense to have a single instance of a service in an application.
- Databases: when it comes to database connections, databases such as MongoDB utilize the singleton pattern.
- Configurations: if there is an object with a specific configuration, you don’t need a new instance every time that configuration object is needed.
For example, think of a printer in an office. The single printer instance is a shared resource amongst all the employees. When an employee needs to use a printer, they do not create a new one. Instead, they are directed to the existing printer. Then, they use that to print.
4. Prototype design pattern
The prototype creational pattern is used to instantiate objects and their default values using an existing object. We are essentially cloning the object and providing the existing properties to the cloned object using the concept of prototypal inheritance.
- To eliminate the overhead of initializing an object
- When you want the system to be independent about how its products are created
- When creating objects from a database where the values are copied to the cloned object
What to learn next
- Factory Pattern
- Abstract Pattern
- Facade Pattern
- Flyweight Pattern
- Iterator Pattern
- Visitor Pattern
- And more
Pathrise is a full service organization that helps people land their dream job in tech. We work extensively with software engineers by providing technical workshops, 1-on-1 mentoring sessions, and pair programming sessions. In addition, we offer guidance on other components of the job search, including resume, GitHub, and LinkedIn optimization, reverse recruiting, cold emailing, behavioral interviewing, salary negotiation, and more.