Chapter 3. Creational Patterns

In the last chapter we took a long look at how to fashion a class. In this chapter we'll look at how to create instances of classes. On the surface it seems like a simple concern but how we create instances of a class can be of great importance.

We take great pains in creating our code so that it be as decoupled as possible. Ensuring that classes have minimal dependence on other classes is the key to building a system that can change fluently with the changing needs of those using the software. Allowing classes to be too closely related means that changes ripple through them like, well, ripples.

One ripple isn't a huge problem but, as you throw more and more changes into the mix, the ripples add up and create interference patterns. Soon the once placid surface is an unrecognizable mess of additive and destructive nodes. This same problem occurs in our applications: the changes magnify and interact in unexpected ways. One place where we tend to forget about coupling is in the creation of objects:

let Westeros;
(function (Westeros) {
  let Ruler = (function () {
    function Ruler() {
      this.house = new Westeros.Houses.Targaryen();
    }
    return Ruler;
  })();
  Westeros.Ruler = Ruler;
})(Westeros || (Westeros = {}));

You can see in this class that the Ruler's house is strongly coupled to the class Targaryen. If this were ever to change then this tight coupling would have to change in a great number of places. This chapter discusses a number of patterns, which were originally presented in the gang of four book, Design Patterns: Elements of Reusable Object-Oriented Software. The goal of these patterns is to improve the degree of coupling in applications and increase the opportunities for code reuse. The patterns are as follows:

  • Abstract factory
  • Builder
  • Factory method
  • Singleton
  • Prototype

Of course not all of these are applicable to JavaScript, but we'll see all about that as we work through the creational patterns.

Abstract factory

The first pattern presented here is a method for creating kits of objects without knowing the concrete types of the objects. Let's continue with the system presented in the preceding section for ruling a kingdom.

For the kingdom in question the ruling house changes with some degree of frequency. In all likelihood there is a degree of battling and fighting during the change of house but we'll ignore that for the moment. Each house will rule the kingdom differently. Some value peace and tranquility and rule as benevolent leaders, while others rule with an iron fist. The rule of a kingdom is too large for a single individual so the king defers some of his decisions to a second in command known as the hand of the king. The king is also advised on matters by a council, which consists of some of the more savvy lords and ladies of the land.

A diagram of the classes in our description look like this:

Abstract factory

Tip

Unified Modeling Language (UML) is a standardized language developed by the Object Management Group, which describes computer systems. There is vocabulary in the language for creating user interaction diagrams, sequence diagrams, and state machines, amongst others. For the purposes of this book we're most interested in class diagrams, which describe the relationship between a set of classes.

The entire UML class diagram vocabulary is extensive and is beyond the scope of this book. However, the Wikipedia article available at https://en.wikipedia.org/wiki/Class_diagram acts as a great introduction as does Derek Banas' excellent video tutorial on class diagrams available at https://www.youtube.com/watch?v=3cmzqZzwNDM.

An issue is that, with the ruling family, and even the member of the ruling family on the throne, changing so frequently, coupling to a concrete family such as Targaryen or Lannister makes our application brittle. Brittle applications do not fare well in an ever-changing world.

An approach to fixing this is to make use of the abstract factory pattern. The abstract factory declares an interface for creating each of the various classes related to the ruling family.

The class diagram of this pattern is rather daunting:

Abstract factory

The abstract factory class may have multiple implementations for each of the various ruling families. These are known as concrete factories and each of them will implement the interface provided by the abstract factory. The concrete factories, in return, will return concrete implementations of the various ruling classes. These concrete classes are known as products.

Let's start by looking at the code for the interface for the abstract factory.

No code? Well, actually that is exactly the case. JavaScript's dynamic nature precludes the need for interfaces to describe classes. Instead of having interfaces we'll just create the classes right off the bat:

Abstract factory

Instead of interfaces, JavaScript trusts that the class you provide implements all the appropriate methods. At runtime the interpreter will attempt to call the method you request and, if it is found, call it. The interpreter simply assumes that if your class implements the method then it is that class. This is known as duck typing.

Note

Duck typing

The name duck typing comes from a 2000 post to the comp.lang.python news group by Alex Martelli in which he wrote:

In other words, don't check whether it IS-a duck: check whether it QUACKS-like-a duck, WALKS-like-a duck, and so on, depending on exactly what subset of duck-like behavior you need to play your language-games with.

I enjoy the possibility that Martelli took the term from the witch-hunt sketch from Monty Python and the Holy Grail. Although I can find no evidence of that, I think it quite likely as the Python programming language takes its name from Monty Python.

Duck typing is a powerful tool in dynamic languages allowing for much less overhead in implementing a class hierarchy. It does, however, introduce some uncertainty. If two classes implement an identically named method which have radically different meanings then there is no way to know if the one being called is the correct one. Consider for example this code:

class Boxer{
  function punch(){}
}
class TicketMachine{
  function punch(){}
}

Both classes have a punch() method but they clearly have different meanings. The JavaScript interpreter has no idea that they are different classes and will happily call punch on either class, even when one doesn't make sense.

Some dynamic languages support a generic method, which is called whenever an undefined method is called. Ruby, for instance, has missing_method, which has proven to be very useful in a number of scenarios. As of writing, there is currently no support for missing_method in JavaScript. However, ECMAScript 2016, the follow up to ECMAScript 2015, defines a new construct called Proxy which will support dynamically wrapping objects, with this one could implement an equivalent of missing_method.

Implementation

To demonstrate an implementation of the Abstract Factory the first thing we'll need is an implementation of the King class. This code provides that implementation:

let KingJoffery= (function () {
  function KingJoffery() {
  }
  KingJoffery.prototype.makeDecision = function () {
    …
  };
  KingJoffery.prototype.marry = function () {
    …
  };
  return KingJoffery;
})();

Note

This code does not include the module structure suggested in Chapter 2, Organizing Code. Including the boiler-plate module code in every example is tedious and you're all smart cookies so you know to put this in modules if you're going to actually use it. The fully modularized code is available in the distributed source code.

This is just a regular concrete class and could really contain any implementation details. We'll also need an implementation of the HandOfTheKing class which is equally unexciting:

let LordTywin = (function () {
  function LordTywin() {
  }
  LordTywin.prototype.makeDecision = function () {
  };
  return LordTywin;
})();

The concrete factory method looks like this:

let LannisterFactory = (function () {
  function LannisterFactory() {
  }
  LannisterFactory.prototype.getKing = function () {
    return new KingJoffery();
  };
  LannisterFactory.prototype.getHandOfTheKing = function ()
  {
    return new LordTywin();
  };
  return LannisterFactory;
})();

This code simply instantiates new instances of each of the required classes and returns them. An alternative implementation for a different ruling family would follow the same general form and might look like:

let TargaryenFactory = (function () {
  function TargaryenFactory() {
  }
  TargaryenFactory.prototype.getKing = function () {
    return new KingAerys();
  };
  TargaryenFactory.prototype.getHandOfTheKing = function () {
    return new LordConnington();
  };
  return TargaryenFactory;
})();

The implementation of the Abstract Factory in JavaScript is much easier than in other languages. However the penalty for this is that you lose the compiler checks, which force a full implementation of either the factory or the products. As we proceed through the rest of the patterns, you'll notice that this is a common theme. Patterns that have a great deal of plumbing in statically typed languages are far simpler but create a greater risk of runtime failure. Appropriate unit tests or a JavaScript compiler can ameliorate this situation.

To make use of the Abstract Factory we'll first need a class that requires the use of some ruling family:

let CourtSession = (function () {
  function CourtSession(abstractFactory) {
    this.abstractFactory = abstractFactory;
    this.COMPLAINT_THRESHOLD = 10;
  }
  CourtSession.prototype.complaintPresented = function (complaint) {
    if (complaint.severity < this.COMPLAINT_THRESHOLD) {
      this.abstractFactory.getHandOfTheKing().makeDecision();
    } else
    this.abstractFactory.getKing().makeDecision();
  };
  return CourtSession;
})();

We can now call this CourtSession class and inject different functionality depending on which factory we pass in:

let courtSession1 = new CourtSession(new TargaryenFactory());
courtSession1.complaintPresented({ severity: 8 });
courtSession1.complaintPresented({ severity: 12 });

let courtSession2 = new CourtSession(new LannisterFactory());
courtSession2.complaintPresented({ severity: 8 });
courtSession2.complaintPresented({ severity: 12 });

Despite the differences between a static language and JavaScript, this pattern remains applicable and useful in JavaScript applications. Creating a kit of objects, which work together, is useful in a number of situations; any time a group of objects need to collaborate to provide functionality but may need to be replaced wholesale. It may also be a useful pattern when attempting to ensure that a set of objects be used together without substitutions.

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

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