Composite

If you read through the section about the singleton pattern and thought, "well, that was simple," don't worry, I have some more complicated patterns to discuss, one of which is the composite pattern. Composites, as the word implies, are objects composed of multiple parts that create a single entity. This single entity serves as the access point for all the parts, which, while simplifying things greatly, can also be deceiving because there’s no implicit way to tell just how many parts the composite contains.

Structure of the composite

The composite is explained best using an illustration. In Figure 1, you can see two different types of objects: containers and galleries are the composites and images are the leaves. A composite can hold children and generally doesn't implement much behavior. A leaf contains most of the behavior, but it cannot hold any children, at least not in the classical composite example.

clip_image001

Figure 1. The structure of a composite

As another example, I'm 100% certain you’ve seen the composite pattern in action before but never really thought about it. The file structure in computers is an example of the composite pattern. If you delete a folder, all of its contents get deleted too, right? That's essentially how the composite pattern works. You can call a method on a composite object higher up on the tree and the message will be delivered down through the hierarchy.

Composite coding example

This example creates an image gallery as an example of the composite pattern. You will have just three levels: album, gallery, and image. The album and galleries will be composites and the images will be the leaves, just like in Figure 1. This is a more defined structure than a composite needs to have, but for this example, it makes sense to limit the levels to only being composites or leaves. A standard composite doesn't limit which levels of the hierarchy that leaves can be on, nor do they limit the number of levels.

To start things off, you create the GalleryComposite "class" used for both the album and the galleries. Please note that I am using jQuery for the DOM manipulation to simplify things.



var GalleryComposite = function (heading, id) {
this.children = [];

this.element = $('')
.append('

' + heading + '

');
}

GalleryComposite.prototype = {
add: function (child) {
this.children.push(child);
this.element.append(child.getElement());
},

remove: function (child) {
for (var node, i = 0; node = this.getChild(i); i++) {
if (node == child) {
this.children.splice(i, 1);
this.element.detach(child.getElement());
return true;
}

if (node.remove(child)) {
return true;
}
}

return false;
},

getChild: function (i) {
return this.children[i];
},

hide: function () {
for (var node, i = 0; node = this.getChild(i); i++) {
node.hide();
}

this.element.hide(0);
},

show: function () {
for (var node, i = 0; node = this.getChild(i); i++) {
node.show();
}

this.element.show(0);
},

getElement: function () {
return this.element;
}
}

There's quite a bit there, so how about I explain it a little bit? The add, remove, and getChild methods are used for constructing the composite. This example won't actually be using remove and getChild, but they are helpful for creating dynamic composites. The hide, show, and getElement methods are used to manipulate the DOM. This composite is designed to be a representation of the gallery that is shown to the user on the page. The composite can control the gallery elements through hide and show. If you call hide on the album, the entire album will disappear, or you can call it on just a single image and just the image will disappear.

Now create the GalleryImage class. Notice that it uses all of the exact same methods as the GalleryComposite. In other words, they implement the same interface, except that the image is a leaf so it doesn't actually do anything for the methods regarding children, as it cannot have any. Using the same interface is required for the composite to work because a composite element doesn't know whether it's adding another composite element or a leaf, so if it tries to call these methods on its children, it needs to work without any errors.



var GalleryImage = function (src, id) {
this.children = [];

this.element = $('')
.attr('id', id)
.attr('src', src);
}

GalleryImage.prototype = {
// Due to this being a leaf, it doesn't use these methods,
// but must implement them to count as implementing the
// Composite interface
add: function () { },

remove: function () { },

getChild: function () { },

hide: function () {
this.element.hide(0);
},

show: function () {
this.element.show(0);
},

getElement: function () {
return this.element;
}
}


Now that you have the object prototypes built, you can use them. Below you can see the code that actually builds the image gallery.

var container = new GalleryComposite('', 'allgalleries');
var gallery1 = new GalleryComposite('Gallery 1', 'gallery1');
var gallery2 = new GalleryComposite('Gallery 2', 'gallery2');
var image1 = new GalleryImage('image1.jpg', 'img1');
var image2 = new GalleryImage('image2.jpg', 'img2');
var image3 = new GalleryImage('image3.jpg', 'img3');
var image4 = new GalleryImage('image4.jpg', 'img4');

gallery1.add(image1);
gallery1.add(image2);

gallery2.add(image3);
gallery2.add(image4);

container.add(gallery1);
container.add(gallery2);

// Make sure to add the top container to the body,
// otherwise it'll never show up.
container.getElement().appendTo('body');
container.show();

Singleton

The singleton pattern is what you use when you want to ensure that only one instance of an object is ever created. In classical object-oriented programming languages, the concepts behind creating a singleton was a bit tricky to wrap your mind around because it involved a class that has both static and non-static properties and methods. I’m talking about JavaScript here though, so with JavaScript being a dynamic language without true classes, the JavaScript version of a singleton is excessively simple.

Why do you need the singleton?

Before I get into implementation details, I should discuss why the singleton pattern is useful for your applications. The ability to ensure you have only one instance of an object can actually come in quite handy. In server-side languages, you might use a singleton for handling a connection to a database because it's just a waste of resources to create more than one database connection for each request. Similarly, in front-end JavaScript, you might want to have an object that handles all AJAX requests be a singleton. A simple rule could be: if it has the exact same functionality every time you create a new instance, then make it a singleton.

This isn't the only reason to make a singleton, though. At least in JavaScript, the singleton allows you to namespace objects and functions to keep them organized and keep them from cluttering the global namespace, which as you probably know is a horrible idea, especially if you use third party code. Using the singleton for name-spacing is also referred to as the module design pattern.

Show me the singleton

To create a singleton, all you really need to do is create an object literal.


var Singleton = {
prop: 1,
another_prop: 'value',
method: function() {…},
another_method: function() {…}
};


You can also create singletons that have private properties and methods, but it's a little bit trickier as it involves using a closure and a self-invoking anonymous function. Inside a function, some local functions and/or variables are declared. You then create and return an object literal, which has some methods that refererence the variables and functions that you declared within the larger function's scope. That outer function is immediatly executed by placing () immediately after the function declaration and the resulting object literal is assigned to a variable. If this is confusing, then take a look over the following code and then I'll explain it some more afterward.




var Singleton = (function() {
var private_property = 0,
private_method = function () {
console.log('This is private');
}

return {
prop: 1,
another_prop: 'value',
method: function() {
private_method();
return private_property;
},
another_method: function() {…}
}
}());


The key is that when a variable is declared with var in front of it inside a function, that variable is only accessible inside the function and by functions that were declared within that function (the functions in the object literal for example). The return statement gives us back the object literal, which gets assigned to Singleton after the outer function executes itself.



Namespacing with the singleton


In JavaScript, namespacing is done by adding objects as properties of another object, so that it is one or more layers deep. This is useful for organizing code into logical sections. While the YUI JavaScript library does this to a degree that I feel is nearly excessive with numerous levels of namespacing, in general it is considered best practice to limit nesting namespaces to only a few lavels or less. The code below is an example of namespacing.



var Namespace = {
Util: {
util_method1: function() {…},
util_method2: function() {…}
},
Ajax: {
ajax_method: function() {…}
},
some_method: function() {…}
};

// Here's what it looks like when it's used
Namespace.Util.util_method1();
Namespace.Ajax.ajax_method();
Namespace.some_method();

The use of namespacing, as I said earlier, keeps global variables to a minumum. Heck, you can even have entire applications attached to a single object namespace named app if that's your perogative.

Literals

Integers


Floating-point literals
Boolean literals
String literals

Integers can be expressed in decimal (base 10), hexadecimal (base 16), and octal (base 8). A decimal integer literal consists of a sequence of digits without a leading 0 (zero). A leading 0 (zero) on an integer literal indicates it is in octal; a leading 0x (or 0X) indicates hexadecimal. Hexadecimal integers can include digits (0-9) and the letters a-f and A-F. Octal integers can include only the digits 0-7. Some examples of integer literals are: 42, 0xFFF, and-345.

Floating-point literals

A floating-point literal can have the following parts: a decimal integer, a decimal point ("."), a fraction (another decimal number), an exponent, and a type suffix. The exponent part is an "e" or "E" followed by an integer, which can be signed (preceded by "+" or "-"). A floating-point literal must have at least one digit, plus either a decimal point or "e" (or "E"). Some examples of floating-point literals are 3.1415, -3.1E12, .1e12, and 2E-12

String literals

A string literal is zero or more characters enclosed in double (") or single (') quotation marks. A string must be delimited by quotation marks of the same type; that is, either both single quotation marks or double quotation marks.

The following are examples of string literals: "blah", 'blah', "1234", "one line \n another line".

In addition to ordinary characters, you can also include special characters in strings, as shown in the last element in the preceding list.

Special Characters

Character
Meaning

\b
backspace

\f
form feed

\n
new line

\r
carriage return

\t
tab

\\
backslash character

For characters not listed in the preceding table, a preceding backslash is ignored, with the exception of a quotation mark and the backslash character itself. You can insert quotation marks inside strings by preceding them with a backslash. This is known as escaping the quotation marks. For example,

var quote = "He read \"The Cremation of Sam McGee\" by R.W. Service."
document.write(quote)

The result of this would be He read "The Cremation of Sam McGee" by R.W. Service. To include a literal backslash inside a string, you must escape the backslash character. For example, to assign the file path c:\temp to a string, use the following:

var home = "c:\\temp"

Variables

You use variables as symbolic names for values in your application. You give variables names by which you refer to them and which must conform to certain rules.

A JavaScript identifier, or name, must start with a letter or underscore ("_"); subsequent characters can also be digits (0-9). Because JavaScript is case sensitive, letters include the characters "A" through "Z" (uppercase) and the characters "a" through "z" (lowercase).

Some examples of legal names are Number_hits, temp99, and _name.

You can declare a variable in two ways:

  • By simply assigning it a value; for example, x = 42
  • With the keyword var; for example, var x = 42

When you set a variable identifier by assignment outside of a function, it is called a global variable, because it is available everywhere in the current document. When you declare a variable within a function, it is called a local variable, because it is available only within the function. Using var is optional, but you need to use it if you want to declare a local variable inside a function that has already been declared as a global variable.

You can access global variables declared in one window or frame from another window or frame by specifying the window or frame name. For example, if a variable called phoneNumber is declared in a FRAMESET document, you can refer to this variable from a child frame as parent.phoneNumber.

Data type conversion

JavaScript is a loosely typed language. That means you do not have to specify the data type of a variable when you declare it, and data types are converted automatically as needed during script execution. So, for example, you could define a variable as follows:

var answer = 42

And later, you could assign the same variable a string value, for example,

answer = "Thanks for all the fish..."

Because JavaScript is loosely typed, this assignment does not cause an error message.

In expressions involving numeric and string values, JavaScript converts the numeric values to strings. For example, consider the following statements:

x = "The answer is " + 42
y = 42 + " is the answer."

The first statement returns the string "The answer is 42." The second statement returns the string "42 is the answer."

Hello Jscript

function greet()
{
alert("Hello JScript");
}

Javascript Review

JavaScript is a compact, object-based scripting language for developing client and server Internet applications. Netscape Navigator interprets JavaScript statements embedded in an HTML page, and LiveWire enables you to create server-based applications similar to Common Gateway Interface (CGI) programs.
JavaScript is Netscape's cross-platform, object-based scripting language for client and server applications. There are two types of JavaScript:

  • Navigator JavaScript, also called client-side JavaScript
  • LiveWire JavaScript, also called server-side JavaScript
JavaScript is a language. Client and server JavaScript differ in numerous ways, but they have the following elements in common:
  • Keywords, statement syntax, and grammar
  • Rules for expressions, variables, and literals
  • Underlying object model (although Navigator and LiveWire have different object frameworks)
  • Built-in objects and functions