Lazy instantiation

If you go into a higher-end coffee shop and place an order for some overly complex beverage (Grande Chai Tea Latte, 3 Pump, Skim Milk, Lite Water, No Foam, Extra Hot anybody?) then that beverage is going to be made on-the-fly and not in advance. Even if the coffee shop knew which orders were going to come in that day, they would still not make all the beverages up front. First, because it would result in a large number of ruined, cold beverages, and second, it would be a very long time for the first customer to get their order if they had to wait for all the orders of the day to be completed.

Instead coffee shops follow a just-in-time approach to crafting beverages. They make them when they're ordered. We can apply a similar approach to our code through the use of a technique known as lazy instantiation or lazy initialization.

Consider an object which is expensive to create; that is to say that it takes a great deal of time to create the object. If we are unsure if the object's value will be needed, we can defer its full creation until later.

Implementation

Let's jump into an example of this. Westeros isn't really big on expensive coffee shops but they do love a good bakery. This bakery takes requests for different bread types in advance and then bakes them all at once should they get an order. However, creating the bread object is an expensive operation so we would like to defer that until somebody actually comes to pick up the bread:

class Bakery {
  constructor() {
    this.requiredBreads = [];
  }
  orderBreadType(breadType) {
    this.requiredBreads.push(breadType);
  }
}

We start by creating a list of bread types to be created as needed. This list is appended to by ordering a bread type:

var Bakery = (function () {
  function Bakery() {
    this.requiredBreads = [];
  }
  Bakery.prototype.orderBreadType = function (breadType) {
    this.requiredBreads.push(breadType);
  };

This allows for breads to be rapidly added to the required bread list without paying the price for each bread to be created.

Now when pickUpBread is called we'll actually create the breads:

pickUpBread(breadType) {
  console.log("Picup of bread " + breadType + " requested");
  if (!this.breads) {
    this.createBreads();
  }
  for (var i = 0; i < this.breads.length; i++) {
    if (this.breads[i].breadType == breadType)
      return this.breads[i];
  }
}
createBreads() {
  this.breads = [];
  for (var i = 0; i < this.requiredBreads.length; i++) {
    this.breads.push(new Bread(this.requiredBreads[i]));
  }
}

Here we call a series of operations:

let bakery = new Westeros.FoodSuppliers.Bakery();
bakery.orderBreadType("Brioche");
bakery.orderBreadType("Anadama bread");
bakery.orderBreadType("Chapati");
bakery.orderBreadType("Focaccia");

console.log(bakery.pickUpBread("Brioche").breadType + "picked up");

This will result in the following:

Pickup of bread Brioche requested.
Bread Brioche created.
Bread Anadama bread created.
Bread Chapati created.
Bread Focaccia created.
Brioche picked up

You can see that the collection of actual breads is left until after the pickup has been requested.

Lazy instantiation can be used to simplify asynchronous programming. Promises are an approach to simplifying callbacks which are common in JavaScript. Instead of building up complicated callbacks, a promise is an object which contains a state and a result. When first called, the promise is in an unresolved state; once the async operation completes, the state is updated to complete and the result is filled in. You can think of the result as being lazily instantiated. We'll look at promises and promise libraries in more detail in Chapter 9, Web Patterns.

Being lazy can save you quite a bit of time in creating expensive objects that end up never being used.

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

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