Design Pattern #1 - Singleton
Tags: javascript, architecture, frontend, learning
Published: 2024-06-07 13:46:49

I’m excited to be starting a new series where we’ll dive a bit into some of the trending design patterns for front-end developers.

Design patterns are a crucial part of software development, offering tried and tested solutions to common problems that can be used to improve collaboration when working with many people on the same project.

In this first article, we’ll be exploring the Singleton pattern that ensures a class has only one instance and provides a global point of access to it. Stay tuned for more articles exploring different design patterns in this series.

## Singleton Pattern

The Singleton Pattern is a type of design pattern that restricts the creation of a class to only one instance. This is useful in scenarios where a single point of control or coordination is required. In other words, it ensures that a class has only one instance, and provides a global point of access to it.

This pattern is often used for configuration data, caches, or connection pools or logging where it's more efficient to have one instance running that can be used by other processes in an application. It also can be useful when you need to maintain state, initialize fields or manage a queue of calls and callbacks.

For instance, if an application has a dropdown list of items that is accessed from various places, a Singleton can manage this shared resource. This ensures that if the list is modified in one place, the changes are reflected across the entire application.

If you need this information to be shared across multiple instances of your application (like different devices), you can use the [Real-time Data Engine](https://docs.superviz.com/sdk/presence/real-time-data-engine) from [SuperViz](https://superviz.com/). Designed with developers in mind, it provides an effortlessly seamless integration into your projects, enabling you to implement design patterns such as the Publisher/Subscriber Pattern. Our engine ensures efficient and real-time updates, transforming your application's responsiveness and overall user experience.

## Singleton Example

Here's a basic example of how this dropdown list might be implemented in JavaScript:

```jsx
let dropdownListItems;
class DropdownList {
    constructor(items = []) {
        if (dropdownListItems) {
            return dropdownListItems;
        }
        
        dropdownListItems = items;
    }

    addItem(item) {
        dropdownListItems.push(item);
    }

    removeItem(item) {
        dropdownListItems = dropdownListItems.filter(i => i !== item);
    }
}

const dropdownList = new DropdownList();
export default dropdownList;

```

This JavaScript code defines a class `DropdownList` and an instance of it.

1. `dropdownListItems` is a variable that is initially `undefined`.
2. The `DropdownList` class is defined with a constructor that accepts an array of items as an argument, defaulting to an empty array if no argument is provided.
3. In the constructor, if `dropdownListItems` is already defined, it returns the one defined. If `dropdownListItems` is not defined, it assigns the `items` argument to `dropdownListItems`.
4. The `DropdownList` class has two methods: `addItem` and `removeItem`.
    - `addItem` method: This method accepts an item as an argument and pushes it to the `dropdownListItems` array.
    - `removeItem` method: This method accepts an item as an argument and removes it from the `dropdownListItems` array. It does this by reassigning `dropdownListItems` to a new array that filters out the item to be removed.
5. An instance of `DropdownList` is created with no arguments, so it will be initialized with an empty array. This instance is stored in the `dropdownList` constant.

### Singleton Pattern with ES2016

The code above shows how to implement the singleton with the ES2015, I choose to show you this way before to make it simpler to understand what the singleton is about.

However, with ES2016 introduced the `static` keyword, which can be used to create a static instance property on the class. This static instance property can be used to hold the single instance of the class. 

```jsx
class DropdownList {
  static dropdownListItems = [];

  constructor(items = []) {
    if (DropdownList.dropdownListItems.length) {
      return DropdownList.dropdownListItems;
    }
    DropdownList.dropdownListItems = items;
  }

  addItem(item) {
    DropdownList.dropdownListItems.push(item);
  }

  removeItem(item) {
    DropdownList.dropdownListItems = DropdownList.dropdownListItems.filter(i => i !== item);
  }
}

const dropdownList = new DropdownList();

export default dropdownList;
```

In this ES2016 version, the instance is a static property on the class itself, rather than a separate variable. This makes it clear that the instance is associated with the class, not just some random variable on top. 

The instance is created when the module is loaded, and the same instance is returned every time the class is imported. This also means that we don’t need the `Object.freeze(player);` anymore.

Stay tuned for more posts in this series where we'll continue to explore different design patterns. Don't forget to follow and like if you found this useful, and feel free to leave any questions you have in the comments section.