Basic JavaScript Design Patterns- Object Creation
Tags: architecture, webdev, programming, javascript
Published: 2021-01-30 21:27:02

**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/**


JavaScript lets us do a lot of things. It’s sometimes too forgiving in its syntax.

To organize our code, we should use some basic design patterns. In this article, we’ll look at some basic object creation patterns that we may use.

### Singleton

The singleton pattern is where we create a single instance of a class.

Since we can create object literals without a constructor in JavaScript, we can create an object easily as follows:

```
const obj = {  
  foo: 'bar'  
};
```

`obj` will also be a standalone object, so defining an object literal follows the singleton pattern.

If we create a new object that has the same structure, we’ll get a different object.

For instance, if we create a new object:

```
const obj2 = {  
  foo: 'bar'  
};
```

Then when we write:

```
obj2 === obj
```

to compare 2 objects, then that’ll return `false` since they’re different references.

### Using new

We can also create a singleton object even if we create them from constructors or classes.

For instance, we can write:

```
let instance;  
class Foo {  
  constructor() {  
    if (!instance) {  
      instance = {  
        foo: 'bar'  
      };  
    }  
    return instance;  
  }  
}
```

Then if we create 2 `Foo` instances:

```
const foo1 = new Foo();  
const foo2 = new Foo();
```

Then when we compare them:

```
console.log(foo1 === foo2);
```

We see `true` logged.

We check if the `instance` is created and then return it as is if it is. Otherwise, we set it to an object.

Since `instance` won’t change after it’s set, all instances are the same.

We can make the `instance` variable private by putting it in an IIFE.

For instance, we can write:

```
const Foo = (() => {  
  let instance;  
  return class {  
    constructor() {  
      if (!instance) {  
        instance = {  
          foo: 'bar'  
        };  
      }  
      return instance;  
    }  
  }  
})()
```

Now we can only access the returned instance rather than looking at the constructor.

### An Instance in a Static Property

Alternatively, we can put the instance of the singleton in a static property of the constructor or class.

For instance, we can write:

```
class Foo {  
  constructor() {  
    if (!Foo.instance) {  
      Foo.instance = {  
        foo: 'bar'  
      };  
    }  
    return Foo.instance;  
  }  
}
```

This way, we set the public `instance` property of the class `Foo` to return the instance if it exists. Otherwise, it’ll create it first.

Now if we write:

```
const foo1 = new Foo();  
const foo2 = new Foo();

console.log(foo1 === foo2);
```

We get the same result as before.

### Instance in a Closure

We can also put the singleton instance in a closure.

For instance, we can write:

```
function Foo() {  
  const instance = this;  
  this.foo = 'bar';  
  Foo = function() {  
    return instance;  
  }  
}
```

We can write a constructor function that gets reassigned to itself at the end of the function.

This will let us return the `instance` while using `this` to assigning instant variables.

This won’t work with the class syntax since it’s created as a constant, so we can’t reassign it to a new value.

### Factory

We can create a factory function to create an object.

A factory function is just a regular function that we can use to create objects.

It’s useful for performing repeated operations when setting up similar objects.

It also offers a way for users of the factory to create objects without the specific class at compile time.

For instance, we can create our own factory function as follows:

```
class Animal {}  
class Dog extends Animal {}  
class Cat extends Animal {}  
class Bird extends Animal {}

const AnimalMaker = type => {  
  if (type === 'dog') {  
    return new Dog()  
  } else if (type === 'cat') {  
    return new Dog()  
  } else if (type === 'bird') {  
    return new Dog()  
  }  
}
```

The code above has the `AnimalMaker` factory function.

It takes the `type` parameter which allows us to create different subclasses given the `type` .

So we can call it as follows:

```
const animal = AnimalMaker('dog');
```

to create a `Dog` instance.

We can also add methods as we wish into the classes:

```
class Animal {  
  walk() {}  
}  
class Dog extends Animal {  
  bark() {}  
}  
class Cat extends Animal {}  
class Bird extends Animal {}

const AnimalMaker = type => {  
  if (type === 'dog') {  
    return new Dog()  
  } else if (type === 'cat') {  
    return new Dog()  
  } else if (type === 'bird') {  
    return new Dog()  
  }  
}
```

This will also work.

### Conclusion

We can create objects with a single instance y using object literals or checking if the instance of the class exists and create it if it doesn’t exist.

Factory functions are useful for creating similar objects.