DEV Community

John Au-Yeung
John Au-Yeung

Posted on • Originally published at thewebdev.info

Basic Building Blocks of JavaScript Design 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 how to building blocks of design patterns that good software are based on.

Design Patterns

We should follow some design patterns so that we can have a good organization of our code.

If our code if well-organized, then working with them won’t be a pain now or in the future.

The Big 4 Object-Oriented Programming Building Blocks

Almost all good design patterns are based on 4 building blocks. They should have the following for them to be good.

Abstraction

Abstraction is one of the building blocks of a good design pattern.

It’s the careful consideration of how we’re going to handle problems.

Abstractions aren’t a programming technique. It’s a way to conceptualize a problem before applying object-oriented techniques.

It’s a way for us to divide our program into natural segments.

If we don’t divide our program into small parts, we’ll have problems with managing the complexity.

We just got divide programs into small, reusable pieces so that we can deal with them.

In JavaScript, we can divide programs in different ways.

We can divide them into functions. So we can write:

const speak = () => {
  //...
}
Enter fullscreen mode Exit fullscreen mode

Then we can call it wherever it’s available.

We can also divide programs into classes. Classes serve as a mechanism to create new objects.

For instance, we can write:

class Animal {
  //...
}
Enter fullscreen mode Exit fullscreen mode

Then we can use the new operator to invoke it as follows:

const animal = new Animal();
Enter fullscreen mode Exit fullscreen mode

We can then access its members. Assuming that it has speak method, we can write:

animal.speak();
Enter fullscreen mode Exit fullscreen mode

Encapsulation

Encapsulation is wrapping methods and data into an object.

We want to do that so different objects won’t know too much about each other.

This way, we won’t have issues with items being accessed when they shouldn’t be.

We should hide as much as possible so that coupling between objects is as loose as possible.

If they’re loosely coupled, then when we change one object, the chance of it breaking the other is lower.

We can divide what we expose to the outside.

The parts that change the most can be hidden and we expose an interface to the outside that doesn’t change that much.

Polymorphism

Polymorphism allows us to write code with different object types and we can decide on which object we want it to be at runtime.

JavaScript doesn’t have a polymorphism in the sense that we can cast them items to whatever we want explicitly.

But since JavaScript objects are dynamic, we can add or remove properties on the fly.

So we can still morph our objects in a way that we want.

We can perform actions according to the type that we set the object to.

We can add and remove properties on the fly.

For instance, we can write:

animal.run = () => {
  //...
}
Enter fullscreen mode Exit fullscreen mode

to define a new method on an object.

We can also merge different objects with Object.assign or the spread syntax.

For example, we can write:

const obj = Object.assign({}, foo, bar);
Enter fullscreen mode Exit fullscreen mode

or:

const obj = {...foo, ...bar };
Enter fullscreen mode Exit fullscreen mode

Both lines of code merge the foo and bar objects together.

Because of JavaScript’s dynamic nature, we don’t cast objects to different types directly for polymorphism.

Inheritance

Inheritance is where our objects inherit the properties and methods of another object.

There are a few ways to do this with JavaScript.

We can use the extends keyword for classes or constructors:

class Animal {
  //...
}

class Dog extends Animal {
  //...
}
Enter fullscreen mode Exit fullscreen mode

The extends keyword indicates that we inherit the members of Animal in the Dog class.

When we create a Dog instance, we’ll see the Animal members in the __proto__ property of the Dog instance.

If we create object literals, we can use the Object.create method as follows:

const parent = {
  foo: 1
};

const child = Object.create(parent);
Enter fullscreen mode Exit fullscreen mode

Once we run the code above, child would have foo in the __proto__ property.

__proto__ is the immediate prototype of the current object.

A prototype is a template object which other objects can inherit members from.

We can access the properties of an object’s prototype by accessing them directly.

So we can write:

child.foo
Enter fullscreen mode Exit fullscreen mode

to access the foo property of child .

Conclusion

Abstraction, encapsulation, polymorphism, and inheritance are the 4 building blocks of object-oriented design patterns.

They provide us with clear ways to divide our code. We should have these in mind when we design our programs.

Top comments (0)