The Strategy Pattern is more useful for programming languages that do not support first-class functions. Fortunately, JavaScript treats everything as an object, and allows for run-time object modification. That enables the use of the strategy pattern quite nicely.
Here’s a simple example for changing the behavior of an object without hard-coding the behavior options into the object itself. It allows for flexible changing of object behavior down the road, without having to refactor an entire code block.
Here’s our object. It’s just a simple object whose constructor takes a string argument. It has one property and one member method.
-
var SimpleText = function(txt) {
-
this.text = txt;
-
this.defaultShowAction = this.show;
-
};
-
SimpleText.prototype.show = function() {
-
alert(this.text);
-
};
One interesting thing to note about the constructor is the second line. It saves the initial show method as a member property, so it can be easily reset later. Note that it’s saved as a public property, so it is possible to even change the default behavior. Here are some example behaviors:
-
var AppendToDocument = function() {
-
var txtNode = document.createTextNode(this.text);
-
document.body.appendChild(txtNode);
-
};
-
var AppendToDocumentWithDiv = function() {
-
var div = document.createElement("DIV");
-
div.appendChild(document.createTextNode(this.text));
-
document.body.appendChild(div);
-
};
Note that they all reference this.text. It doesn’t make much sense now, so I’ll go into it after we create our test case:
-
var txt = new SimpleText("Hello World!");
-
txt.show(); // alerts "Hello World!"
-
txt.show = AppendToDocument;
-
txt.show(); // appends "Hello World!" to the end of the document
-
// as a text node
-
txt.show = AppendToDocumentWithDiv;
-
txt.show(); // wraps "Hello World!" in a div element and appends
-
// it to the document.
-
txt.show = txt.defaultShowAction;
-
txt.show(); // alerts it again
When adding a method to an instantiated object this way, the this keyword will reference the object it’s attached to. Pretty handy, right? Now you can redefine the behavior of any JavaScript object as you go. It’s inherent in the language, unlike Java, where you must wrap each new behavior in a class which implements the requisite behavior interface. In this way, JavaScript is a little bit more powerful than Java. On the one hand, it’s really easy to quickly redefine behaviors of an object.
On the other hand, it opens up many pitfalls. The new behavior may not necessarily conform to what the object is expecting, and there is no way to define what a method’s signature must look like. If someone else is using your code, they may not know that your object is built to let them do this. It can also make things messily difficult to debug later on, if the implementation of SimpleText changes down the line - say, if you rename the text member to textblock - you’ll have to go through and change every single one of your behavior methods!
Look to Part 2 (coming soon!) to see how you can overcome these pitfalls.
Tags: Design pattern, JavaScript, Programming, Strategy Pattern
![Reblog this post [with Zemanta]](http://img.zemanta.com/reblog_e.png?x-id=4e6e6667-dd12-4684-a8ec-3c78f40fd61c)