Basic JavaScript Design Patterns — Decorators, Facades, and Proxies
Tags: architecture, webdev, programming, javascript
Published: 2021-01-30 21:27:40

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

The organize our code, we should use some basic design patterns. In the article, we’ll look at decorators, facades, and proxies.

### Decorator

Decorators let us add functionality to an object on the fly.

JavaScript has decorators now so that we can use them to create our own decorator and mutate objects on the fly.

For instance, we can create one as follows:

```
const foo = () => {
  return (target, name, descriptor) => {
    descriptor.value = "foo";
    return descriptor;
  };
};

class Foo {
  @foo()
  bar() {
    return "baz";
  }
}

const f = new Foo();
console.log(f.bar);
```

A decorator in JavaScript, it’s just a function that returns a function with the parameters `target` , `name` and `descriptor` .

`descriptor` is the property descriptor, so we can set the `value` , `writable` , and `enumerable` properties for it.

Our `foo` decorator transformed the `value` property of it to the string `'foo'` .

So we get that `Foo` instance’s `bar` property becomes the string `'foo'` instead of a method.

JavaScript decorators are still experimental syntax, so we need Babel to use it.

The `@babel/plugin-proposal-decorators` will let us use decorators in our JavaScript projects.

The function returned by the decorator function has 2 other parameters.

The `target` is the constructor or class that the decorator is in.

The `name` parameter is the string of the entity that it’s modifying.

We can use it to modify other entities in a class.

### Facade

The facade is a simple pattern that lets us provide an alternative interface to an object.

We can use it to hide the complex implementation behind a facade.

This is good because we don’t want users of our code to know everything.

The facade is very simple and we don’t have to do much.

We can also use it to combine multiple operations that are called together into one.

For instance, if we have multiple methods that are called together, then they can be put together into one method.

We can implement the facade pattern as follows:

```
const adder = {
  add() {
    //...
  },
}

const subtractor = {
  subtract() {
    //...
  },
}
const facade = {
  calc() {
    adder.add();
    subtractor.subtract();
  }
}
```

We created a `facade` object that combines the `add` and `subtract` methods.

The facade pattern is used to create an interface in front of multiple objects.

Also, we can use it to handle the intricacies of browsers.

Some browsers may not have the `preventDefault` or `stopPropgation` methods, so we may want to check that they exist before calling them:

```
const facade = {
  stop(e) {
    if (typeof e.preventDefault === "function") {
      e.preventDefault();
    }
    if (typeof e.stopPropagation === "function") {
      e.stopPropagation();
    }
    //...
  }
}
```

Now we call always call `stop` and don’t have to worry about their existence since we check that they exist before calling them.

### Proxy

The proxy pattern is where one object acts as an interface to another object.

The difference between proxy and facade patterns are that we can proxies create interfaces for one object.

But facades can be interfaces for anything.

We can create a proxy as follows:

```
const obj = {
  foo() {
    //...
  },

  bar() {
    //...
  },
}

const proxy = {
  call() {
    obj.foo();
    obj.bar();
  }
}
```

We use the `proxy` to call both `foo` and `bar` in `obj` .

This pattern is good for lazy initialization.

This is where we only initialize something when it’s used.

Instead of always running the initialization code, we run the initialization code only when needed.

### Proxy As a Cache

Proxies can act as a cache. We can check the cache for the results before returning the result.

If we have it, then we return the result from the cache.

Otherwise, we generate the result, put it in the cache, and then return it.

For instance, we can write:

```
const obj = {
  add() {
    //...
  }
}

const proxy = {
  cache: {},
  add(result) {
    if (!cache[result]) {
      cache[result] = obj.add();
      //...
    }
    return cache[result];
  }
}
```

Now we can do expensive operations only when needed instead of always doing it.

### Conclusion

The decorator pattern can be used to change entities on the fly.

JavaScript has experimental decorators that let us do that.

Facades and proxies can both be used to hide the implementations of objects.

Proxies if for hiding one object, and facades can be used to hide more complex implementations.