Categories
JavaScript Design Patterns

JavaScript Design Patterns — Adapters and Facades

Design patterns are the basis of any good software. JavaScript programs are no exception.

In this article, we’ll look at the adapter and facade patterns.

Adapter

The adapter pattern is useful for creating a consistent interface for another object.

The object we’re creating an interface for doesn’t fit with how it’s used.

Therefore, we create an adapter so that we can use them easily.

It also hides the implementation so that we can use it easily and with low coupling.

For instance, we can create an adapter object as follows:

const backEnd = {
  setAttribute(key, value) {
    //.,,
  },
  getAttribute() {
    //...
  }
}

const personAdapter = {
  setFirstName(name) {
    backEnd.setAttribute('firstName', name);
  },
  setLastName(name) {
    backEnd.setAttribute('lastName', name);
  },
  getFirstName() {
    backEnd.getAttribute('firstName');
  },
  getLastName() {
    backEnd.getAttribute('lastName');
  }
}

We created an adapter object called personAdapter so that we can use backEnd to set all the attributes.

The adapter has an interface that people can understand more easily since the method names are explicit.

Other objects or classes can use the object to manipulate the attributes.

We can use adapters to create interfaces that we want to expose to the public any way we want.

Inheriting Objects with Adapters

With adapters, we can also create an interface for multiple classes or objects.

For instance, we can write:

const backEnd = {
  setAttribute(key, value) {
    //.,,
  },
  getAttribute() {
    //...
  }
}

const parentAdapter = {
  //...
  getAdapterName() {
    //...
  }
}

const personAdapter = Object.create(parentAdapter);

personAdapter.setFirstName = (name) => {
  backEnd.setAttribute('firstName', name);
};

personAdapter.setLastName = (name) => {
  backEnd.setAttribute('lastName', name);
};

personAdapter.getFirstName = () => {
  backEnd.getAttribute('firstName');
};

personAdapter.getLastName = () => {
  backEnd.getAttribute('lastName');
}

In the code above, we created personAdapter with Object.create , which allows us to inherit from another parent object.

So we get the getAdapterName method from the parentAdapter prototype object.

Then we add our own methods to personAdapter .

Now we can get inherited methods from another object plus the methods in our own adapter object in the adapter.

Likewise, we can do the same with the class syntax.

For instance, we can create an adapter class instead of an object.

We can write:

const backEnd = {
  setAttribute(key, value) {
    //.,,
  },
  getAttribute() {
    //...
  }
}

class ParentAdapter {
  //...
  getAdapterName() {
    //...
  }
}

class PersonAdapter extends ParentAdapter {
  setFirstName(name) {
    backEnd.setAttribute('firstName', name);
  }

  setLastName(name) {
    backEnd.setAttribute('lastName', name);
  }

  getFirstName() {
    backEnd.getAttribute('firstName');
  }

  getLastName() {
    backEnd.getAttribute('lastName');
  }

}

const personAdapter = new PersonAdapter();
console.log(personAdapter);

The code above has a PersonAdapter and ParentAdapter classes instead of objects.

We used the extends keyword to inherit members from ParentAdapter .

This is another way we can inherit members from a parent entity.

Facade Pattern

We can use the facade pattern to create a class or object to hide the implementation of something complex behind it.

This is used to create an easy to use interface for the outside while keeping the complex implementation of something inside.

For instance, we can write:

const complexProduct = {
  setShortName(name) {
    //...
  },

  setLongName(name) {
    //...
  },

  setPrice(price) {
    //...
  },

  setDiscount(discount) {
    //...
  },
  //...
}

const productFacade = {
  setName(type, name) {
    if (type === 'shortName') {
      complexProduct.setShortName(name);
    } else if (type === 'longName') {
      complexProduct.setLongName(name);
    }
  }
  //...
}

We created a productFacade that has some methods that call various methods in the complexProduct object.

This way, we can use the facade to simplify what we do, and also reduce the coupling to the complexProduct object.

We let the productFacade object communicates with the complexProduct object.

It also serves to reduce coupling from complex objects.

In addition, a facade can also create an interface for something that won’t change as often as what’s behind it.

An interface that doesn’t change as often is good since more changes mean more risks of bugs.

Likewise, we can create a facade class that does the same thing as follows:

const complexProduct = {
  setShortName(name) {
    //...
  },

  setLongName(name) {
    //...
  },

  setPrice(price) {
    //...
  },

  setDiscount(discount) {
    //...
  },
  //...
}

class ProductFacade {
  setName(type, name) {
    if (type === 'shortName') {
      complexProduct.setShortName(name);
    } else if (type === 'longName') {
      complexProduct.setLongName(name);
    }
  }
  //...
}

Then we can create an instance of ProductFacade instead of using the object literal directly.

A facade can be used to manipulate one or more objects. That’s different from the adapter pattern, where we make an adapter for one object.

Conclusion

We can use the adapter pattern to hide the implementation of one object bu creating an interface that’s easier to work with to the outside.

The facade pattern lets us hide complex implementations behind one interface that can be used instead of one or more complex objects being the facade.

Categories
JavaScript Design Patterns

Basic Building Blocks of JavaScript Design Patterns

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 = () => {
  //...
}

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 {
  //...
}

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

const animal = new Animal();

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

animal.speak();

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 = () => {
  //...
}

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);

or:

const obj = {...foo, ...bar };

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 {
  //...
}

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);

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

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.

Categories
JavaScript Design Patterns

Basic JavaScript Design Patterns — Decorators, Facades, and Proxies

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.

Categories
JavaScript Design Patterns

Basic JavaScript Design Patterns — Factories, Iterators, and Decorators

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 the article, we’ll look at factories, iterators, and decorators.

Built-in Object Factory

JavaScript’s standard library comes with several factory methods.

They include Object , Boolean , Number , String , and Array .

For instance, we can use the Boolean factory function as follows:

const bool = Boolean(1);

Then bool is true since 1 is truthy.

All they do is return different objects or values according to what we pass in.

Many of them are useful. However, the Object constructor isn’t all that useful since we can create objects with object literals.

Iterator

JavaScript has iterators since ES6.

Therefore, we don’t have to write anything from scratch to implement this pattern

We just have to use a generator function to return the values we’re looking for sequentially.

Then we can call the built-in next function to get the value returned after the generator is returned from the generator function.

For instance, we can write:

const numGen = function*() {
  while (true) {
    yield (Math.random() * 100).toFixed(1);
  }
}

to create a generator function.

A generator function is denoted by the function* keyword. There’s an asterisk after the function keyword.

The yield keyword will return the next value sequentially.

Then we can use it to return a random number as follows:

const nums = numGen();
console.log(nums.next().value);
console.log(nums.next().value);
console.log(nums.next().value);

We first call numGen to return an iterator.

Then we call nums.next().value to get the values we want.

We can also have a generator function that returns a finite number of values.

For instance, we can write:

const numGen = function*() {
  const arr = [1, 2, 3];
  for (const a of arr) {
    yield a;
  }
}

const nums = numGen();
let value = nums.next().value;
while (value) {
  console.log(value);
  value = nums.next().value;
}

In the code above, we changed the numGen function to return an array’s entries in sequence.

This way, we can call the next method in a loop to get the entries in sequence with the next method.

In addition to value property, the object returned by the next method also has the done property.

So we can write:

const nums = numGen();
let {
  done,
  value
} = nums.next();

while (!done) {
  console.log(value);
  const next = nums.next();
  done = next.done;
  value = next.value;
}

Once all the values are returned, done will be set to true.

Additional Functionality

If we want more functionality, then we’ve to implement our own iterator.

For instance, if we want rewind functionality, we can create our own iterator as follows:

const iterator = (() => {
  const arr = [1, 2, 3];
  let index = 0;
  return {
    next() {
      index++;
      return arr[index];
    },
    rewind() {
      index--;
      return arr[index];
    }
  }
})();

We just added an array with the next method to move to the next arr entry and rewind to move to the previous arr entry.

Then we can use iterator as follows:

console.log(iterator.next());
console.log(iterator.rewind());

And we see:

2
1

from the console log output.

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.

Conclusion

JavaScript has various factory functions that let us create objects.

There’s the Object , Boolean , Number , String functions and more.

JavaScript has built-in support for iterators. However, if we want more functionality that it provides, then we’ve to implement our own.

Decorators exist in JavaScript, so we can use it to create decorators to modify properties.

Categories
JavaScript Design Patterns

Basic JavaScript Design Patterns- Object Creation

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.