DEV Community

Cover image for Design Patterns: Unlock the Secrets to Writing Exceptional Code
Mukhil Padmanabhan
Mukhil Padmanabhan

Posted on

Design Patterns: Unlock the Secrets to Writing Exceptional Code

Design Patterns: The Key to Writing Better Code

When you first start learning to code, you tend to concentrate on trying to solve problems or writing functions. However, as your applications grow, you quickly learn that writing maintainable, reusable and efficient code can be a challenge. That's when design patterns come in.

Design patterns are solutions that can be applied to solve a particular problem in the general design of a program. Design patterns usually involve designing objects, classes, or methods that interact with each other. They are optimized, reusable solutions to the programming problems and have specific names and scopes.

Design patterns let you write better code that is more easily maintained, more scalable and robust. In this post, we’ll explore few must-know software development design patterns for anyone looking to become an interview rock-star.


What Are Design Patterns?

A design pattern is essentially a reusable blueprint for solving a problem that occurs frequently in software design. It’s not considered a complete solution but rather a description or template for how to solve the problem using object-oriented programming techniques. So, it’s not code! Rather, it’s something of an outline or structure you can apply to your code.

Why Use Design Patterns?

Design patterns are important for the following reasons:

  • Reusability: Patterns give you clean code structures that you can reuse all over your project.
  • Maintainability: Patterns make your code more maintainable and extensible.
  • It saves time : While writing code if you come across a design problem, then high chances are that someone else also would have faced same or similar issue. This means solution to your problem lies in reusing their pattern and avoid reinventing the wheel.
  • Easy communication : Design patterns provides you with a language to solve particular problems in particular contexts.

Singleton Pattern

What it is: Ensures that only one instance of a class is created and provides a global point of access to it.

Use the Singleton pattern when you want to eliminate the option of instantiating more than one object e.g. just one connection to a database.

Example:

Think of a light switch. You only need one switch to control the lights in a room. The Singleton pattern is similar—you create only one instance of a class and all parts of the program can access that object.

In software, if you have a logging framework that records events or errors, you would want them all to log to the same file. You could use the Singleton pattern to make this logging object available to everyone.

Image description

Advantages:

  • Saves memory because object is not created each time we call the constructor.
  • You are creating a single point of control and failure for your global resources.

Cons:

  • Can lead to tight coupling, and then it's harder to test or change stuff later.

Observer Pattern

What it is: Observer pattern is used when there is one-to-many relationship between objects such as if one object is modified, its depenedent objects are to be notified automatically.

You use it when you have an object that changes, and other objects should automatically update based on that change.

Example:

Think about a newsletter subscription. Each time the new edition of the magazine is published, all subscribers receive this update.

Actually, in programming, it is very widely used in UI systems. For instance, an weather app - the weather data is subject and temperature display and forecast chart are observers - so each time the new weather arrive - all observers are refresh automatically

Image description

Benefits:

  • It promotes loose coupling between objects coming at the cost of increased complexity.
  • Great for writing responsive UI systems!

Cons:

  • Can lead to complex update chains if not handled properly.

Strategy Pattern

What it is: A pattern that enables an algorithm's behavior to be selected at runtime.

When to use: When you have multiple ways to perform a task and want to switch between them dynamically.

In what scenarios can we best use a switch statement?

Think of Google Maps. If you want to navigate to a place, you can enter different modes of transportation such as driving, walking, or cycling. The Strategy pattern allows the app to dynamically switch these modes of transportation depending on situation or the user's preference.

In programming, if you have some logic such as sorting and there are multiple algorithms available like bubble sort, merge sort, quicksort etc., then all this becomes very messy because typically if..else blocks will cause algorithm logic and business/execution logic wrapped in each other.Strategy pattern provides a way to dynamically select algorithm at runtime without the application client noticing it i.e. it provides an ability to change individual class behaviour/libraries at run-time.

Image description

Benefits:

  • It makes switching algorithms at runtime simple.
  • You can centralize the algorithm and eliminate duplicate code.

Cons:

  • Can make code more complex by adding multiple strategy classes.

Decorator Pattern

What is it? A pattern that allows behavior to be added to an individual object, either statically or dynamically, without affecting the behavior of other objects from the same class.

When to use: When you want to add extra functionality to an object without modifying its class.

Example:

Think about coffee. You can have coffee alone or you’ll be able to add some milk, some sugar, or some cream… All these elements are right here so as to add on prime of the espresso itself, enhancing it with out altering the essence of the espresso.

Image description

In programming phrases in case you have a easy notification system and also you wish to add new options like email, SMS or push notifications, you need to use Decorator design pattern for dynamically including these options with out altering the unique notification class.

Benefits:

  • Adds new functionality to the existing code without modifying it.
  • Allows you to mix and match responsibilities dynamically.

Cons

  • Can result in over-complication if too many decorators are used.

Adapter Pattern

What it is: A pattern that allows incompatible interfaces or systems to work together by providing a wrapper that translates one interface into another.

When to use: When you want to use an existing class or system but it doesn’t fit the expected interface.

Example:

Think of a power plug adapter. When you travel to a country with different power outlets, you use an adapter to connect your device.

In programming, if you have a legacy system that uses an old interface but you need it to work with a new system, you can use the Adapter pattern to make the old and new systems compatible.

Image description

Advantages

  • Allows you to use your legacy code or systems without having to modify them.
  • This makes your code more usable.

Cons:

  • Can introduce another layer of abstraction which make the code harder to understand.

Command Pattern

What it is : The command pattern is a design pattern in which an object is used to encapsulate all information needed to performs an actions or triggers an event at later time.

This should be used when you want to issue requests, e.g., undo/redo operations, or if you need to log user actions.

Example:

Imagine a remote control. You press a button and it sends a command (turn on, turn off, change the channel) and there is knowledge encapsulated in the television on how to perform those commands.

In software when you want to implement undo/redo for actions performed in a text editor like typing or deleting letters you can model each action as its own object with an interface that has an undo() and redo() method.

Benefits:

  • It decouples the sender of a request from receiver.
  • Easier to implement undo/redo operations.

Cons:

  • If the number of commands becomes large, this can be complicated further.

Proxy Pattern

What it is: A way to control access to an object by using another object as a stand-in.

You would use this kind of pattern when you want to control access to an object. For example: for security reasons or because you have a lot of resource-heavy objects that would take too long to load all at once.

Example:

Think of a personal assistant. The assistant controls access to their boss, scheduling meetings and avoiding interruptions. The assistant is acting as a proxy for the boss.

In programming, the Proxy pattern is used to limit access to an object. Controls access to images or data sets, until they are needed. This saves memory and processing power.

Image description

Benefits:

  • Controls access to an object, hiding the creation of the object and providing lazy loading and improved performance.
  • Can add extra layers of security.

Cons:

  • Can introduce unnecessary layers if not used properly.

Builder Pattern

What it is: A pattern that helps in constructing complex objects step by step, separating the construction process from the actual representation of the object.

When to use: When you need to create complex objects with many optional parts.

Example:

Think about making a custom pizza. You go through and pick your crust, sauce, toppings, and size one by one.

In programming when you want to create a complex object like car or house which have lot of optional attributes you don’t use constructor with too many fields rather than that you build object step by step.

Image description

Benefits

  • It makes software easier to maintain.
  • Provides clear, readable code for creating objects step by step.

Cons

  • Can be an overkill for simpler objects.

Conclusion: Why You Should Use Design Patterns

Design patterns are a collection of best practices that address common software design problems. When you use design patterns in your code, you get the following benefits:

  1. Code becomes more modular, flexible and elegant.
  2. Effort required to refactor code becomes less.
  3. Code is more readable and understandable as it has already been tested and used by others.

So, next time if you come across any design problem, try using one of these patterns and I am sure you will be able to come up with better solution. Keep coding!

Top comments (0)