The Mediator Pattern in JavaScript
Tags: javascript, node, webdev
Published: 2019-10-30 22:32:24

Find me on [medium](https://medium.com/@jsmanifest)
Join my [newsletter](https://app.getresponse.com/site2/javascript-newsletter?u=zpBtw&webforms_id=SM2hz)

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:

```js
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,
  }
})()
```

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](https://medium.com/@jsmanifest)
Join my [newsletter](https://app.getresponse.com/site2/javascript-newsletter?u=zpBtw&webforms_id=SM2hz)