Have you ever been on a team and you need to start a project from scratch? That's usually the case in many start-ups and other small companies. There are so many different programming languages, architectures, and other concerns that it can be difficult to figure out where to start. That's where design patterns come in.
A design pattern is like a template for your project. It uses certain conventions and you can expect a specific kind of behavior from them. These patterns were made up of many developers' experiences so they are really like different sets of best practices. You and your team get to decide which set of best practices is the most useful for your project. Based on the design pattern you choose, you all will start to have expectations for what the code should be doing and what vocabulary you all will be using.
Programming design patterns can be used across all programming languages and can be used to fit any project because they only give you a general outline of a solution. There are 23 official patterns from the book, Design Patterns - Elements of Reusable Object-Oriented Software, which is considered one of the most influential books on object-oriented theory and software development. I'm going to cover 4 of the design patterns here just to give you some insight to what a few of the patterns are and when you would use them.
Singleton Design Pattern
The main thing you need to know about the singleton pattern is that it only allows a class to have a single instance and it uses a global variable to store that instance. You'll use lazy loading to make sure that there is only one instance of the class because it will only create the class when you need it. That prevents multiple instances from being created. Most of the time this gets implemented in the constructor.
An example of a singleton that you probably use all the time is a state object in JavaScript. If you work with some of the front-end frameworks like React or Angular, you know all about how the parent component's state gets distributed to the child components. This is a great example of singletons in action because you never want more than one instance of that state object.
Strategy Design Pattern
The strategy is pattern is like an advanced version of an if else statement. It's basically where you make an interface for a method you have in your base class. This interface is then used to find the right implementation of that method from one of the derived classes. The implementation, in this case, will be decided at runtime based on the client.
This pattern is incredibly useful in situations where you have required and optional methods for a class. Some instances of that class won't need the optional methods and that causes a problem for inheritance solutions. You could use interfaces for the optional methods, but then you would have to write the implementation every time you used that class since there would be no default implementation.
That's where the strategy pattern saves us. Instead of the client looking for an implementation, it delegates to a strategy interface and the strategy finds the right implementation.
Observer Design Pattern
If you've ever used the MVC pattern, you've already used the observer design pattern. The observer pattern is like the View part of MVC. You have a subject that holds all of the data and the state of that data. Then you have observers, like users, that will pull data from the subject when the data has been updated.
There are so many applications for this design pattern that it became an integral part of MVC. Sending user notifications, updating, filters, and handling subscribers can all be done using the observer patter.
Decorator Design Pattern
Using the decorator design pattern is fairly simple. You can have a base class with methods and properties that are present when you make a new object with the class. Now say you have some instances of the class that need methods or properties that didn't come from the base class. You can add those extra methods and properties to the base class, but that could mess up your other instances. You could even make subclasses to hold specific methods and properties you need that you can't put in your base class.
Either of those approaches will solve your problem, but they are clunky and inefficient. That's where the decorator pattern steps in. Instead of making your code base ugly just to add a few things to an object instance, you can tack on those specific things directly to the instance. So if you need to add a new property that holds the time for an instance, you can use the decorator pattern to add it directly to that particular instance and it won't affect any other instances of that class object.
Have you ever ordered food online? Then you've probably encountered the decorator pattern. If you're getting a sandwich and you want to add special toppings, the website isn't adding those toppings to every sandwich every current user is trying to order. It just adds those special toppings to your instance of that sandwich. When you need to work with multiple instances of an object that need values added dynamically like this, the decorator pattern is a good option.
I used to think that design patterns were these crazy, far-out software development guidelines. Then I found out I use them all the time! A few of the patterns I covered are used in so many applications that it would blow your mind. They are just theory at the end of the day. It's up to us as developers to use that theory in ways that make our applications easy to implement and maintain.
Have you used any of the other design patterns for your projects? Most places usually pick a design pattern for their projects and stick with it so I'd like to hear from you guys about what you use.
Hey! You should follow me on Twitter because reasons: https://twitter.com/FlippedCoding