DEV Community

John Au-Yeung
John Au-Yeung

Posted on • Originally published at thewebdev.info

JavaScript Design Patterns — Chain of Responsibility, Singleton, and Flyweight Patterns

Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62

Subscribe to my email list now at http://jauyeung.net/subscribe/

Design patterns are the basis of any good software. JavaScript programs are no exception.

In this article, we’ll look at the chain of responsibility, singleton, and flyweight patterns.

Chain of Responsibility Pattern

The chain of responsibility is similar to the observer pattern, except that it sends the notification to one object, and then that object sends the notification to another object, and so on.

In the observer pattern, the notification is sent to all the observers at the same time.

For instance, if we send something to one object and then that object picks that up and does something with and send that to another and so on, then that implements the chain of responsibility patterns.

We can implement that as follows:

const backend = {
  receive(data) {
    // do something with data
  }
}

const middleLayer = {
  notify(data) {
    backend.receive(data);
  }
}

const frontEnd = {
  notify(data) {
    middleLayer.notify(data);
  }
}
Enter fullscreen mode Exit fullscreen mode

In the code above, we have the frontEnd , which calls the notify method of the middleLayer object, which in turn called the backend ‘s receive method.

This way, we can pass data between them with one method seamlessly.

As long as we don’t expose any other methods that do communication between both objects, we have a clean way of sending data between frontEnd and middleLayer and backEnd .

Singleton

The singleton pattern is where we only instantiate one instance of an object.

In JavaScript, we can create objects with one instance by creating an object literal.

We can create one by writing:

const obj = {
  foo: 1,
  bar: 'baz'
}
Enter fullscreen mode Exit fullscreen mode

An object literal is just sets of key-value pairs, where the value can also be other objects.

If we use classes, we can also write:

class Foo {
  constructor() {
    if (!Foo.instance) {
      Foo.instance = {
        foo: 1,
        bar: 2
      }
    }
    return Foo.instance;
  }
}
Enter fullscreen mode Exit fullscreen mode

We assigned the created instance to the instance property of Foo .

Then when we create the constructor, we check the instance property to see if anything’s created for it.

If there’s nothing assigned to it then we assign an object to it.

Then we return Foo.instance so that we get the instance.

Now if we create 2 instances of Foo :

const foo = new Foo();
const bar = new Foo();
Enter fullscreen mode Exit fullscreen mode

Then we can see if they’re the same instance by writing:

console.log(foo === bar);
Enter fullscreen mode Exit fullscreen mode

We should get true since they both reference the same instance.

Singletons are handy for creating objects that are used by multiple pieces of code to store data in a central place.

If we don’t want conflicts in how data is accessed, then we can create a singleton instance of a class or an object literal to make sure that there are no issues with conflicts.

Flyweight Pattern

The flyweight pattern is where we restrict object creation,

We create a set of small objects that each consume a smaller amount of resources.

These objects sit behind a flyweight object, which is used to interact with these objects,

Those objects also interact with our code.

This way, we get the benefits of a big object, while we interact with smaller objects that are more manageable.

For instance, we can implement it as follows:

class Student {
 //..
}

const studentIdentity = {
 getIdentity(){
   const student = new Student();
    //..
    return {
    //...
    }
  }
}

const studentScore = {
 getScore(){
   const student = new Student();
    //..
    return {
    //...
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

We have a Student class that represents a student’s data.

Then in the studentIdentity and studentScore objects, we have methods to get his or her identity or score respectively.

This way, we don’t have to put all the methods into the Student class.

Instead, we have methods outside of it that are smaller that we can use to deal with specific kinds of student data.

Conclusion

We can use the singleton pattern to create one-off objects.

We can either create class instances with only one instance or with object literals.

The flyweight pattern is where we create smaller objects to deal with big objects, thereby reducing complexity.

The chain of responsibility pattern lets us send data from one object to another in a series fashion.

Top comments (0)