DEV Community

Cover image for The Mediator Pattern in JavaScript
jsmanifest
jsmanifest

Posted on • Edited on • Originally published at jsmanifest.com

The Mediator Pattern in JavaScript

Find me on medium
Join my newsletter

In JavaScript, a widely used and powerful pattern is the Module Pattern. It can be incredibly simple to implement but the fact that it enables developers to encapsulate their code makes it one of the most versatile patterns to build robust code. When you look inside the source code of JavaScript libraries, you're most likely looking at an implementation of this pattern. In addition, they're also most likely a singleton object--where only one instance exists throughout the lifetime of an app.

It may be difficult for newcomers in JavaScript to understand the module pattern as there are several variations that exist. However, it's worth all the time and trouble because you'll be using the module pattern to write most of your apps once you've understood the concept.

Variations

Immediately Invoked Function Expression

Arguably the most popular variation of the module pattern is the IIFE (Immediately Invoked Function Expression). These are essentially functions that invoke immediately and should return an object (an interface, in other words), which will be used as the module.

Inside these functions are code that is private and accessible only within that function's scope unless the returned interface (publicly accessible by the outside world) provides methods that can access them somehow.

Modules

As you may have guessed, the module pattern lets you create modules.

We will implement our own module using the IIFE. This allows us to assign the return value of an IIFE directly onto a variable so that we can use it just like a JavaScript module.

For example, lets pretend that we are creating an RPG game and the first thing we decided to do was create a sorceress class. The sorceress will have methods to inflict damage to their targets. In just about every RPG game, sorceresses usually cast spells or magic, so we'll define an interface that mimic this concept:

const sorceress = (function() {
  const sideEffects = {
    intervals: {},
  }

  function _fireBolt(target, customDamage) {
    target.hp -= customDamage !== undefined ? customDamage : 15
  }

  function _thunderBolt(target) {
    target.hp -= 15
  }

  function blizzard(target) {
    target.hp -= 15
  }

  function _applyThunderBoltSideEffects(
    target,
    { interval = 1000, timeout = 15000 } = {},
  ) {
    if (sideEffects.intervals[target.id]) {
      clearInterval(sideEffects.intervals[target.id])
    }

    sideEffects.intervals[target.id] = setInterval(() => {
      target.hp -= 1
    }, interval)

    setTimeout(() => {
      if (sideEffects.intervals[target.id]) {
        clearInterval(sideEffects.intervals[target.id])
      }
    }, timeout)
  }

  return {
    fireBolt(target, options) {
      if (options) {
        _fireBolt(target, options.customDamage)
      } else {
        _fireBolt(target)
      }
    },
    thunderBolt(target) {
      _thunderBolt(target)
      _applyThunderBoltSideEffects(target)
    },
    blizzard,
  }
})()
Enter fullscreen mode Exit fullscreen mode

In this example, our sorceress class has three methods: sorceress.fireBolt, sorceress.thunderBolt, and sorceress.blizzard.

Inside the module, we declared three private functions and one public function. We can obviously tell that that the functions prefixed with underscores _ are the private functions while the others are public. This isn't how we create public and private code inside though, we do it by what's being returned using closure. We returned an object which is exposed to the caller. Having the power to declare private and public variables is what makes the module pattern one of the most powerful patterns in JavaScript.

By keeping things private we can prevent code from being revealed to the "outside world".

Find me on medium
Join my newsletter

Top comments (4)

Collapse
 
abhinav1217 profile image
Abhinav Kulshreshtha • Edited

Can you elaborate as if I am five?

This isn't how we create public and private code inside though,
 we do it by what's being returned using closure. 
We returned an object which is exposed to the caller.
Collapse
 
remco profile image
Remco

I was about to write an elaborate explanation, but Douglas Crockford already wrote an extensive article about this 😄:

crockford.com/javascript/private.html

The keyword is "closure", an example is visible in a constructor-function:

function Person(firstName, lastName) {
  function fullName() {
    return `${firstName} ${lastName}`;
  }

  this.introduce = function() {
    console.log(fullName());
  }
}

When a Person is created we can call introduce on it, but not fullName, essentially making fullName private.

Keep in mind, closures are not limited to constructors! A closure is defined as "a function with its variable scope". Simplified that means that a function 'remembers' the scope it was defined in.

I hope it helps!

For more info you can check developer.mozilla.org/en-US/docs/W...

Collapse
 
oaphi profile image
Oleg Valter

There is probably a mistake in the title - the pattern described is a revealing module pattern, not the mediator, which essentially is an extension of the observable pattern (in a sense Mediator acts as both an observable [publishing to subscribers] and an observer [receiving messages from subscribers] )

Collapse
 
ankitasinghal profile image
Ankita Singhal

Are the Mediator pattern and module pattern the same ?