Introduction

The singleton design pattern is probably the simplest and most common pattern in JavaScript.

So why should you use the singleton pattern?

  • Encapsulation of members & functions
  • Creates its own Namespace
  • A singleton is a single instance object
  • Encourages code reuse
  • Improves readability because you can logically organise your code

When to use a Singleton

The point of a singleton is to only have one instance. A shopping cart is a good example of something that you may want only a single instance of at one time.

Types of Singletons

Object Literals

The simplest form of Singleton is an object literal. This loose form of Singleton cannot be instantiated. All of the members are now accessible through the Singleton variable, accessible through dot notation.

var myCart = {
   self: this,
   totalCost: 0,
   totalQty: 0,
   cart: {},
   getCart: function(){ },
   updateCart: function(){ }
};

alert( "Total cost: $" + myCart.totalCost );

Singleton Public & Private Members, using Closures

By using closures, we can create Private and Public Members and Functions. This pattern is more commonly called the Module Pattern.

var myCart = function(){
    // Private
    var self = this;
    var totalCost = 0;
    var totalQty = 0;
    var cart = {};

    return {
        // Public
        getCart: function(){ },
        updateCart: function(){ }
    };
}();

Now for an Example

The JavaScript

// Assumes use of the jQuery library
var myCart = {
    init: function(callback) {
        $.ajax({
            dataType: "json",
            url: "cart.php",
            complete: callback,
            success: myCart.updateCart,
            error: myCart.cartError
        });
    },
    cartError: function(XMLHttpRequest, textStatus, errorThrow) {
        alert( "Yikes! " + (textStatus||errorThrow));
    },
    getCart: function(){
        return myCart.cart;
    },
    updateCart: function(jsn){
        myCart.totalCost = myCart.totalQty = 0;
        myCart.cart = $.each(jsn.cart, function(key){

            myCart.totalCost += this;
            myCart.totalQty++;
        });
    }
};

$(document).ready(function(){
   myCart.init(function(){
       $("<div/>").attr("id", "cart").css({color: "blue"}).appendTo("body");
       $.each(myCart.getCart(), function(key){
           $("#cart").append("<div>"+key+": $"+this+"</div>");
       });
       $("<div>Total cost: $"+myCart.totalCost+"</div>").css({"fontWeight":"bold"}).appendTo("body");
   });
});

cart.php – Returning a JSON object

<?
    header('Content-Type: application/json; charset=utf-8');
?>
{
    cart: {
        "Clock": 200,
        "Wine": 100,
        "xBox": 400,
        "iPod": 300
    }
}

The Result:

Singleton Example