The Module design pattern was initially created to offer a combination of private and public encapsulation for classes in traditional software development.
When utilizing the Module design pattern, it can be beneficial to establish a basic template to facilitate getting started with it. This template typically includes components for namespace management, along with definitions for public and private variables.
In JavaScript, the Module pattern serves to simulate the concept of classes by enabling the inclusion of both public and private methods and variables within a single object. This approach helps isolate specific elements from the global scope, reducing the risk of function name conflicts with other scripts on the page.
var myNamespace = (function () {
var myPrivateVar, myPrivateMethod;
// Initialize a private counter variable
myPrivateVar = 0;
// Define a private function that logs arguments
myPrivateMethod = function( foo ) {
console.log( foo );
};
return {
// Public variable
myPublicVar: "foo",
// Public function utilizing private elements
myPublicFunction: function( bar ) {
// Increment private counter
myPrivateVar++;
// Call private method using bar argument
myPrivateMethod( bar );
}
};
})();
Benefits
What makes the Module pattern a preferred choice? Firstly, it offers a cleaner approach for developers transitioning from an object-oriented background compared to true encapsulation, especially in a JavaScript context.
Secondly, it supports private data, allowing public parts of the code to interact with private ones while preventing external access to the class's private components.
Drawbacks
One drawback of the Module pattern is that altering visibility requires modifications to all instances where the member is accessed since public and private members are accessed differently.
Additionally, it's not possible to access private members in subsequently added methods of the object. Despite these drawbacks, the Module pattern remains valuable and, when employed effectively, has the potential to enhance application structure.
The Revealing Module Pattern
Building upon the Module pattern, let's explore a refined version - Christian Heilmann’s Revealing Module pattern.
Heilmann introduced the Revealing Module pattern due to his frustration with repeating the main object's name to call a public method from another or access public variables. He also disliked switching to object literal notation as required by the Module pattern to expose desired elements publicly.
This innovation involves defining all functions and variables in the private scope, then returning an anonymous object containing references to private functionality intended for public use.
An illustration of implementing the Revealing Module pattern is shown below
var myRevealingModule = (function () {
var privateVar = "Ben Cherry",
publicVar = "Hey there!";
function privateFunction() {
console.log( "Name:" + privateVar );
}
function publicSetName( strName ) {
privateVar = strName;
}
function publicGetName() {
privateFunction();
}
// Expose public pointers to
// private functions and properties
return {
setName: publicSetName,
greeting: publicVar,
getName: publicGetName
};
})();
myRevealingModule.setName( "Paul Kinlan" );
Advantages
This pattern promotes script syntax consistency and enhances readability by clearly indicating which functions and variables may be accessed publicly at the module's conclusion.
Disadvantages
An issue with this pattern arises if a private function references a public one; overriding the public function becomes challenging in case of updates. The pattern primarily pertains to private elements and does not apply to public members, particularly functions.
Moreover, public object members referencing private variables must adhere to the restriction on patching discussed earlier.