Friday, June 13, 2008

The Factory pattern (101)

The simplest way to create new objects is to use the new keywords and a concreate class. The extra complexity of creating and maintaining a factory only makes sense in certian situations, which are outlined in this section.

If you need to create objects with the same interface but different implementations, a factory method or a simple factory object can simplify the process of choosing which implementation is used. This can happen implicitly in Ajax request where the type of connection object created depends on factors such as the percieved bandwidth and network latency. In these situations, you usually have a number of classes that implement the same interface and can be treated identically. In Javascript this is the most common reason for using the factory pattern.
Many Small Objects in one Large Object
A factory method can be useful for creating an object that encapsulates a lot of smaller objects. As an example , consider the constructor for a biycicle objects. A bicycle is comprised of many smaller subsystems;wheels, a frame, a drive train, brakes. If you do not want to tightly couple one of those subsystems to the lager object, but instead want to be able to choose one out many subsystems at run-time, a factory method is ideal. Using this technique, you could create all of the bicycles with a certain type of chain on one day, and change that type the next day if you find one that is better suited to yyour needs. Making this changes is easy because the bicycles do not depend on a specific type of chain in their constructor.

Example:(Ajax request Example)
A common task in any web page these days is to make an asynchronious request using Ajax. depending on the user's browser, you will have to instatiate one of several different classes in order to get an object that can be used to make a request. If you are making more than one Ajax request in your code, it makes sense to abstract this object creation code into a class and to create a wrapper for the different steps it takes to actually make the request. A simple factory works very well here to create an instant of either XMLHttpRequest or ActiveXObject, depending on the browser's capabilities:
Code
/* SimpleHandler interface. */

var SimpleHandler ={
request:function( method , url , calback , postVars)
{
var self=SimpleHandler;
/* This calls the factory method createXhrObject
* to return an instant of the request handler
* depending on the kind of browser the
* client is using
*/
var xhr=self.createXhrObject();
xhr.onreadystatechange=function()
{
if(xhr.readyState!==4) return;
(xhr.status==200)?
callback.success(xhr.responseText):
callback.failure(xhr.status);
};
xhr.open( method , url , postVars);
if(method !=='POST') postVars=null;
xhr.send(postVars);
},
/* The factory method that create an
* instant of the request object
* depending on the browser type
*/
createXhrObject:function()
{
var methods=[
function(){return new XMLHttpRequest();},
function(){ return new ActiveXObject('Msxml2.XMLHTTP');},
function(){ return new ActiveXObject('Microsoft.XMLHTTP');}
];
for(var i=0 ; var len=method.length ; i<>
{
try
{
methods[i]();
}
catch(e)
{
continue;
}
/* if we get to this point, methods[i] worked */
var self= SimpleHandler
self.createXhrObject= methods[i];
return methods[i];
}

/* if we get to this point anyway, none of the methods worked */

throw new Error('Simplehandler: Could not create an Ajax request handler');
},

}
To use this factory example you need to know the method of request, whether POST or GET,
the url you will be sending you request to, the data you want to send to the server,
the callback function that handles response from
the server. Now the callback function is actually an object with two functions namely, success and fialure
It is usually defined as follows
var callback={success:function(responseText){alert('Success: ' + responseText);},
failure:function(statusCode){alert('Failure ' + statusCode);
};
So to do the actual request you do this

SimpleHandler.request(method , url , data);
This simple call first, gets the parameters you want to send to the server, the url to send it to,
the method of sending POST or GET, it then internally determines the type of browser you are using in order to instantiate the correct request handler for the transaction.
an instance of XMLHttpRequest object indicate that you are using a browser that support the geko engine (Firefox,Safari,Apple etc). An instance of ActivexObject with the Msxml2.XMLHTTP parameter indicates that you are using the latest microsoft browser app- IE 7.0 and an instance of ActiveXObject with parameter Microsoft.XMLHTTP indicates that you are using version of IE less than 7.0
The convinience method request performs the steps needed to send off a request and process the reponse. it creates an XHR object, configures it ans sends the request. The interesting part is the creation of the XHR object. The factory method createXhrObject returns an XHR object based on what is available in the current environment. The first time it is run, it will test three different ways of creating an XHR object, and when it finds one that works, it will return the object created and overwrite itself with the function used to create the object. This new function becomes the createXhrObject method. This techniques , can be used to create functions and methods that store complex calculations so that they do not have to be repeated. All of the complex setup code is called once, the first time the method is executed, and after that only the browser-specific code is executed. This is a form of caching technique on the client side that utilizies the browser specific codes only for optimised execution.
Watchout for a review of the Bridge pattern in javascript in my next post

No comments: