Categories
Object-Oriented JavaScript

Object-Oriented JavaScript — Singletons and Decorators

Spread the love

JavaScript is partly an object-oriented language.

To learn JavaScript, we got to learn the object-oriented parts of JavaScript.

In this article, we’ll look at some basic design patterns.

Class-Like Singleton

We can create a singleton object by storing the class instance in a global object.

For instance, we can write:

function Foo() {
  if (typeof globalFoo === "undefined") {
    globalFoo = this;
  }
  return globalFoo;
}

then we can create a Foo instance by writing:

const a = new Foo();
const b = new Foo();
console.log(a === b);

And the console log should log true since we store the existing instance in a global variable.

Then we returned it if it’s not undefined .

Singleton Stored in the Property of the Constructor

We know we shouldn’t use global variables, so we can store the singleton instance as a property of the constructor instead.

Functions can have properties since they are objects.

So we can write:

function Foo() {
  if (typeof Foo.instance === "undefined") {
    Foo.instance = this;
  }
  return Foo.instance;
}

The only change is that we store the property in the instance instead of in a global variable.

We can also store it in a private property if we put it in a function.

So we can write:

const Foo = (() => {
  let instance;
  return function() {
    if (typeof instance === "undefined") {
      instance = this;
    }
    return instance;
  }
})();

and do the same thing.

This way, we can’t accidentally change the instance to something else.

Factory Pattern

The factory pattern is creational design pattern.

It deals with creating objects.

The factory is a function that can help us create similar types of objects with one function.

For instance, we can create a function by writing:

const createElement = (type, url) => {
  if (type === 'Image') {
    return new Image(url);
  }
  if (type === 'Link') {
    return new Link(url);
  }
  if (type === 'Text') {
    return new Text(url);
  }
}

We return the constructor instance based on the type value.

And we also take the url that’s used with the constructors.

Decorator Pattern

The decorator pattern is a structural pattern.

We can use this pattern to extend the functionality of objects.

With this pattern, we can extend an object’s functionality by picking the decorators that we want to apply to the object.

For instance, we can write:

function Person(name) {
  this.name = name;
  this.say = function() {
    console.log(this.name);
  };
}

function DecoratedPerson(person, street, city) {
  this.person = person;
  this.person = person.name;
  this.street = street;
  this.city = city;
  this.say = function() {
    console.log(this.name, this.street, this.city);
  };
}

We have 2 constructors the Person and DecoratedPerson classes.

Person is the class that we use as the base for the DecoratedPerson class.

The DecoratedPerson class adds extra properties on top of the Person class.

This way, we keep the interface of DecoratedPerson the same as the Person constructor for the ones that come from Person .

But we add more properties exclusive to the DecoratedPerson class.

Conclusion

We can create singleton objects with a class like syntax.

The decorator pattern lets us extend the functionality of constructors.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *