We accomplish a lot refactoring our JavaScript code from a “loose” pattern to a more easy-to-read “object-oriented” pattern in out last article. (You can find the article here: Refactoring JavaScript Legacy to Object Oriented)
Now is time to use a real pattern and start making our JavaScript code more elegant. In this next step, we are going to take this single object and apply the Module Design pattern to it. Our goal is to accomplish some kind of public and private protection in our code, and the Module Design Pattern is a good first step.
This is our single object created in the last article:
script type="text/javascript"> var s = { stockApples: 0, msgInStock: "Yes, we have apples in stock.", msgOutOfStock: "No, we don't have apples in stock.", addToStock: function (count) { this.stockApples += count; }, currentStock: function () { return this.stockApples; }, displayCurrentStock: function () { $("#customerFeedback").text("Current number of apples in stock: " + this.stockApples); }, addApples: function () { var number = parseInt($("#numberOfAddApples").val()); this.stockApples += number; }, sellApples: function () { var numberSold = parseInt($("#numberOfSoldApples").val()); this.stockApples -= numberSold; } } </script>
Refactoring Using the Module Design Pattern
I am going to resume what the Module Design pattern is, but you can find a complete explanation here: https://addyosmani.com/resources/essentialjsdesignpatterns/book/#modulepatternjavascript
- Provides both private and public encapsulation for classes.
- Used to emulate the concept on classes (public\private methods and variables) found in other languages like Java and C#.
- Shields particular parts from global scope. Reduction of function names conflicts.
- With this pattern, only a public API is returned, keeping everything else within the closure private.
Here is the same code refactored using the Module Design pattern:
<script type="text/javascript"> var stockModule = (function () { // private variables var stockApples = 0; // Private functions function addToStock(count) { stockApples += count; }; function reduceStock(count) { stockApples -= count; } function currentStock() { return stockApples; }; return { // Public functions displayCurrentStock: function () { $("#customerFeedback").text("Current number of apples in stock: " + currentStock()); }, addApples: function () { var number = parseInt($("#numberOfAddApples").val()); addToStock(number); }, sellApples: function () { var numberSold = parseInt($("#numberOfSoldApples").val()); reduceStock(numberSold); } }; })(); // Use console to test your functions exposure. //console.log(stockModule.); </script> <div id="content"> <p> <label for="numberOfAddApples">Number of Apples to Add:</label> <input type="text" id="numberOfAddApples" /> <button id="addApples" onclick="stockModule.addApples()">Add</button> </p> <p> <label for="numberOfSoldApples">Number of Apples Sold:</label> <input type="text" id="numberOfSoldApples" /> <button id="sellApples" onclick="stockModule.sellApples()">Sell</button> </p> <p><button id="btnCurrentStock" onclick="stockModule.displayCurrentStock()">Display Current Stock</button><br /></p> <h4>Customer Feedback:</h4> <span id="customerFeedback"></span> </div>
Intellisense is cleaner now, showing only the PUBLIC functions available to the user:
That’s it. Our refactoring is complete. You are now making good use of the Module Design pattern. In our next article, we are going to improve our design by using the Module Reveal Design Pattern.
Don’t forget to leave your questions and comments. I will try to answer them all and please share this article with your friends.