Proxy

The final pattern presented in this chapter is the proxy. In the previous section I mentioned how it is expensive to create objects and how we would like to avoid creating too many of them. The proxy pattern provides a method of controlling the creation and use of expensive objects. The UML of the proxy pattern looks like the following diagram:

Proxy

As you can see, the proxy mirrors the interface of the actual instance. It is substituted in for the instance in all the clients and, typically, wraps a private instance of the class. There are a number of places where the proxy pattern can be of use:

  • Lazy instantiation of an expensive object
  • Protection of secret data
  • Stubbing for remote method invocation
  • Interposing additional actions before or after method invocation

Often an object is expensive to instantiate and we don't want to have instances created before they're actually used. In this case the proxy can check its internal instance and, if not yet initiated, create it before passing on the method call. This is known as lazy instantiation.

If a class has been designed without any security in mind but now requires some, this can be provided through the use of a proxy. The proxy will check the call and only pass on the method call in cases where the security checks out.

The proxy may be used to simply provide an interface to methods that are invoked somewhere else. In fact, this is exactly how a number of web socket libraries function, proxying calls back to the web server.

Finally, there may be cases where it is useful to interpose some functionality into the method invocation. This could be logging of parameters, validating of parameters, altering results, or any number of things.

Implementation

Let's take a look at a Westeros example where method interposition is needed. As tends to happen, the units of measurement for liquids vary greatly from one side of the land to the other. In the north, one might buy a pint of beer, while in the south, one would buy it by the dragon. This causes no end of confusion and code duplication, but can be solved by wrapping classes that care about measurement in proxies.

For example, this code is for a barrel calculator which estimates the number of barrels needed to ship a quantity of liquid:

class BarrelCalculator {
  calculateNumberNeeded(volume) {
    return Math.ceil(volume / 157);
  }
}

Although it is not well documented, here this version takes pints as a volume parameter. A proxy is created which deals with the transformation thusly:

class DragonBarrelCalculator {
  calculateNumberNeeded(volume) {
    if (this._barrelCalculator == null)
      this._barrelCalculator = new BarrelCalculator();
    return this._barrelCalculator.calculateNumberNeeded(volume * .77);
  }
}

Equally we might create another proxy for a pint-based barrel calculator:

class PintBarrelCalculator {
  calculateNumberNeeded(volume) {
    if (this._barrelCalculator == null)
      this._barrelCalculator = new BarrelCalculator();
    return this._barrelCalculator.calculateNumberNeeded(volume * 1.2);
  }
}

This proxy class does the unit conversion for us and helps alleviate some confusion around units. Some languages, such as F#, support the concept of units of measure. In effect it is a typing system which is overlaid over simple data types such as integers, preventing programmers from making mistakes such as adding a number representing pints to one representing liters. Out of the box in JavaScript there is no such capability. Using a library such as JS-Quantities (http://gentooboontoo.github.io/js-quantities/) is an option however. If you look at it, you'll see the syntax is quite painful. This is because JavaScript doesn't permit operator overloading. Having seen how weird adding things such as an empty array to an empty array are (it results in an empty string), I think perhaps we can be thankful that operator overloading isn't supported.

If we wanted to protect against accidentally using the wrong sort of calculator when we have pints and think we have dragons, then we could stop with our primitive obsession and use a type for the quantity, a sort of poor person's units of measure:

class PintUnit {
  constructor(unit, quantity) {
    this.quanity = quantity;
  }
}

This can then be used as a guard in the proxy:

class PintBarrelCalculator {
  calculateNumberNeeded(volume) {
    if(PintUnit.prototype == Object.getPrototypeOf(volume))
      //throw some sort of error or compensate
    if (this._barrelCalculator == null)
      this._barrelCalculator = new BarrelCalculator();
    return this._barrelCalculator.calculateNumberNeeded(volume * 1.2);
  }
}

As you can see, we end up with pretty much what JS-Quantities does but in a more ES6 form.

The proxy is absolutely a useful pattern within JavaScript. I already mentioned that it is used by web socket libraries when generating stubs but it finds itself useful in countless other locations.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset