What are some common software design patterns and when should they be used?

💻 Hey there! 🖐🏼

Today, we're talking about software design patterns – those tried and true solutions to common programming problems that make our lives as software engineers just a little bit easier. 🤓

I remember working with my team lead at WebPT and asking him, what design patterns do we use here. It's safe to say, he stared at me and was a bit perplex.

He didn't know how to answer because we use a lot of them, it all depends on the problem being solved.

But first, let's start with the basics:

What are software design patterns? 🤔

Software design patterns are reusable solutions to common design problems in software development. They provide a standard approach to solving these problems and can be used as a starting point when designing software. 💡

So, what are some common design patterns? 🤔

There are many different design patterns, but some common ones include:

Singleton

  • Singleton: This design pattern ensures that a class has only one instance, and provides a global point of access to it. 🏙️
class Singleton {
  static instance = null;
  static getInstance() {
    if (Singleton.instance == null) {
      Singleton.instance = new Singleton();
    }
    return Singleton.instance;
  }
}

const singleton1 = Singleton.getInstance();
const singleton2 = Singleton.getInstance();
console.log(singleton1 === singleton2); // true

Factory

  • This design pattern provides an interface for creating objects in a super class, but allows subclasses to alter the type of objects that will be created. 🏭

Here's an example of how you might use the factory pattern in JavaScript:

class AnimalFactory {
  static createAnimal(type) {
    if (type === 'dog') {
      return new Dog();
    } else if (type === 'cat') {
      return new Cat();
    }
  }
}

class Dog {
  bark() {
    console.log('Woof!');
  }
}

class Cat {
  meow() {
    console.log('Meow!');
  }
}

const dog = AnimalFactory.createAnimal('dog');
dog.bark(); // 'Woof!'
const cat = AnimalFactory.createAnimal('cat');
cat.meow(); // 'Meow!'

Observer

  • This design pattern defines a one-to-many dependency between objects, so that when one object changes state, all of its dependents are notified and updated automatically. 📡

Here's an example of how you might use the observer pattern in JavaScript:

class Subject {
  observers = [];
  addObserver(observer) {
    this.observers.push(observer);
  }
  removeObserver(observer) {
    this.observers = this.observers.filter(o => o !== observer);
  }
  notifyObservers() {
    this.observers.forEach(observer => observer.update());
  }
}

class Observer {
  update() {
    // update implementation goes here
  }
}

const subject = new Subject();
const observer1 = new Observer();
const observer2 = new Observer();
subject.addObserver(observer1);
subject.addObserver(observer2);
subject.notifyObservers();

The MVC pattern

  • This pattern divides the application into three components: the model, which represents the data and business logic; the view, which represents the user interface; and the controller, which handles input and communicates with the model and view. This pattern is useful for organizing and separating concerns in larger applications.
honestly one of my favorites if you work at enterprises
class Model {
  data = {};
  update(key, value) {
    this.data[key] = value;
  }
}

class View {
  render(data) {
    // render implementation goes here
  }
}

class Controller {
  model;
  view;
  constructor(model, view) {
    this.model = model;
    this.view = view;
  }
  update(key, value) {
    this.model.update(key, value);
    this.view.render(this.model.data);
  }
}

const model = new Model();
const view = new View();
const controller = new Controller(model, view);
controller.update('key', 'value');

When do you use them?

Software design patterns can be a useful tool in your developer toolkit 🧰 when you encounter common design problems 🤔 and want to use proven solutions 💪 that have been successful for other developers.

There are many different patterns to choose from 📚, and the appropriate one will depend on the specific needs of your application 💻. Some common factors that may influence the decision to use a design pattern include:

  • The size and complexity of the application: Design patterns are often more useful in larger, more complex applications where there are many moving parts and a need to manage dependencies between different components.
  • The level of abstraction: Some design patterns are more abstract and can be used in a variety of different contexts, while others are more specific and are only applicable in certain situations.
  • The level of flexibility and customization needed: Some design patterns provide more flexibility and customization than others, so you should choose a pattern that meets the specific needs of your application.

Ultimately, the decision to use a design pattern should be based on the needs of your app and the specific design problem you are trying to solve 🔍.

Hope this helps! 👋🏾

You've successfully subscribed to Tech Dad - A Premium Newsletter for Engineering Leadership
Great! Next, complete checkout to get full access to all premium content.
Error! Could not sign up. invalid link.
Welcome back! You've successfully signed in.
Error! Could not sign in. Please try again.
Success! Your account is fully activated, you now have access to all content.
Error! Stripe checkout failed.
Success! Your billing info is updated.
Error! Billing info update failed.