[Coding] JavaScript Patterns (Ch. 7)

Posted by Khatharsis on June 25, 2013

This chapter is aptly named “Design Patterns” and is the longest. It builds on the Gang of Four’s design patterns, implementing their concepts in JavaScript.

A singleton means to only have one instance of a specific class. That is, each time an object is created from a class, the object should be the same as the previous objects created before it–the reference will point to the same object. In JavaScript, new objects are already singletons. If two objects are created to contain the exact same properties and values, then compared against each other, they will not be equal. If you want to implement a variable or set of variables that point to the same object (via the new keyword, so a constructor is used), there are a couple of viable methods: cache a static property in the constructor or wrap the instance in a closure. There are some pros and cons to each method, but I won’t go into detail or post the code.

The factory pattern is usually a class or a static method of class that creates objects. The “factory” is responsible for handling repeating operations for setting up objects and offers a way to create objects without knowing its type at compile time. Objects that are created by the factory inherit from the same parent class. Often, the factory is part of the parent class. One method to implement a factory is to have a method that accepts a string which maps to a particular constructor method (e.g., factory('Box') will then call a constructor named Box). The Object in JavaScript is an example of a built-in factory. When a primitive is passed in, such as a number, it will automatically create a Number object.

The iterator pattern is fairly straightforward. You have an object containing some aggregate data and a next() method to properly traverse through that data. hasNext() is another good method to implement, along with rewind() and current(). The actual implementation involves storing the data in a private variable (i.e., outside code cannot access it directly) as well as having the internal pointer to the next available element private so outside code must use the publicly offered methods (e.g., next()) in order to obtain the data.

The decorator pattern has been brought up before and is just the ability to add functionality to an object dynamically at runtime. The example in the book is selling an item in a certain country that requires specific sets of taxes. The base object is the base price and a decorator() method takes a string that maps to the different types of taxes (similar to the singleton pattern). There are a couple of ways of implementing this pattern. The first is to use inheritance through a constructor and a prototype method. The second does away with the inheritance (although it still uses a constructor) and instead uses a list, which has the added bonus of “undecorating” if that is necessary.

The strategy pattern allows algorithm selection at runtime enabling clients to choose which algorithm they want to use based on the context of what they are trying to accomplish. A typical use is form validation. A Validator object has a config property which is an object containing properties of required fields and types for those fields. The Validator also has a validate() method, which takes in the data from the form and iterates through each field, checking against the config property. The type of the field that is acceptable is a string that maps to a function that checks for that appropriate type, similar to the factory and decorator patterns.

The premise of the facade pattern is to provide a wrapper method that when called, executes a set of methods together. This pattern is helpful for code reduction when two or more methods are often called together. The facade method simply wraps up the method bundle into a single method call. This pattern is also useful for redesign and refactoring in the case of replacing an object with a new implementation, but still requiring the old object to function as-is. A facade can be used to wrap up the new code using the new API so that when the time is appropriate to fully replacing the old object, there is less client code to modify because recent client code already uses the new API.

The proxy pattern sits between the client of an object and the object itself, acting as a guardian to that object. This pattern is useful for performance purposes, such as with lazy initialization in which initializing an object is expensive, especially when the client never uses it. What occurs is the request to initialize the object is passed to the proxy, which holds the request until it is sure that the client will use the object.

Despite the simple explanation for the proxy pattern, one actual use is quite interesting. The example in the book involves a network request when a checkbox is checked to fetch a particular video corresponding to the checkbox’s value. The request is first sent to the proxy, which introduces a delay so that if the user checks multiple boxes within a set amount of time, only one network request is sent rather than multiple. Another good use for the proxy is to use it to store a cache of the results from previous network requests, eliminating the need to send the same request multiple times over the network.

The mediator pattern can be imagined like having a central hub (the mediator), which is connected to everything else (I’ll call them “nodes”), sort of like a wagon wheel. The nodes are independent of each other and rely on the mediator to communicate from one another. The majority of the implementation (including logic) takes place in the mediator object. The node objects contain methods which are called by the mediator, but serve more as helper functions for the mediator rather than full objects of their own, such as displaying a value but not storing the value itself – the mediator passes the value to the node’s method, and that method formats it a certain way for display to the screen.

The observer or subscriber/publisher or custom events pattern promotes loose coupling. Rather than directly calling another object’s method, like with the mediator pattern, this pattern relies on one object (the observer) subscribing to another object (the publisher) and receiving notifications when the publisher performs a specific activity. To implement this pattern, the publisher object needs to have four properties: subscribers (an array of subscribers), subscribe() (adds a new subscriber to the array), unsubscribe() (removes a subscriber from the array), publish() (loops through the subscribers and calls the methods provided when they signed up). A subscriber is added via subscribe() and passes a method it wants to have executed during the publish() method.

I gave a high level overview, focusing more on the theory rather than practical application because this chapter is actually quite dense when taking into account the implementation. I felt being aware of the patterns would be more useful in this summary and a deep-dive would be more appropriate when I find an actual use for any one of these patterns.