Skip to main content

Module Pattern

Encapsulate code using closures to create private scope

Pattern Overview

📦 Module Pattern

The Module Pattern uses closures to create encapsulated modules with private variables and methods, exposing only a public API. It's fundamental to JavaScript's module system and provides namespace management.

Core Concepts

🔹 IIFE (Immediately Invoked Function Expression) - Creates private scope
🔹 Closures - Enable access to private variables from public methods
🔹 Public API - Object returned with methods/properties to expose
🔹 Private State - Variables and functions accessible only within module

Real-World Applications

Library Development - jQuery, Lodash use module patterns for encapsulation Application State - Manage app state without global variables Utility Functions - Group related functionality with shared private state Configuration Management - Encapsulate settings with controlled access

Encapsulation Benefits

Private Variables - Cannot be accessed from outside the module Namespace Management - Prevents global scope pollution API Control - Only expose what users should access State Protection - Internal state cannot be corrupted externally

Modern Alternatives

ES6 Modules - Native import/export system TypeScript Namespaces - Compile-time module organization Class-based Encapsulation - Private fields and methods Module Bundlers - Webpack, Rollup provide module isolation

Implementation Benefits

True privacy - Private variables cannot be accessed externally
Controlled API - Expose only intended functionality
Namespace isolation - Prevent naming collisions
Singleton behavior - Single instance with shared state

Examples:
Create counter with private count variable that cannot be directly modified
Input:
const counter = createCounterInstance();

console.log('Initial:', counter.getCurrentValue());
counter.increment();
counter.increment();
console.log('After increments:', counter.getCurrentValue());

// Try to access private variables (this won't work)
console.log('Private count:', (counter as any).count); // undefined

console.log('History:', counter.getHistory());
Output:
Initial: 0
[Counter] increment: 1
[Counter] increment: 2
After increments: 2
Private count: undefined
History: [1, 2]
Manage shopping cart with private item storage and validation
Input:
const cart = createShoppingCart();

cart.addItem({ id: '1', name: 'Laptop', price: 999, quantity: 1 });
cart.addItem({ id: '2', name: 'Mouse', price: 25, quantity: 2 });

console.log('Items:', cart.getItemCount());
console.log('Total quantity:', cart.getTotalQuantity());
console.log('Total price: $' + cart.getTotal());

cart.setDiscountRate(0.1);
console.log('With 10% discount: $' + cart.getTotal());
Output:
Items: 2
Total quantity: 3
Total price: $1049
With 10% discount: $944.1
User authentication with private session management and security features
Input:
const auth = createAuthSystem();

console.log('Initially authenticated:', auth.isAuthenticated());

const loginResult = auth.login('admin', 'admin123');
console.log('Login result:', loginResult.success);
console.log('Current user:', auth.getCurrentUser()?.username);
console.log('Has admin role:', auth.hasRole('admin'));

auth.logout();
console.log('After logout:', auth.isAuthenticated());
Output:
Initially authenticated: false
Login result: true
Current user: admin
Has admin role: true
After logout: false

Concepts

design patternssoftware architecturecode organizationobject-oriented programming

Complexity Analysis

Time:O(1)
Space:O(n)

Implementation

counter-module

Time: O(1) | Space: O(n)
// Classic Module Pattern using IIFE
const CounterModule = (function() {
  // Private variables
  let count = 0;
  let history: number[] = [];
  
  // Private functions
  function log(action: string, value: number) {
    console.log(`[Counter] ${action}: ${value}`);
  }
  
  // Public API
  return {
    increment(): number {
      count++;
      history.push(count);
      log('increment', count);
      return count;
    },
    
    decrement(): number {
      count--;
      history.push(count);
      log('decrement', count);
      return count;
    },
    
    getCurrentValue(): number {
      return count;
    },
    
    getHistory(): readonly number[] {
      return [...history]; // Return copy to prevent external modification
    },
    
    reset(): void {
      count = 0;
      history = [];
      log('reset', count);
    }
  };
})();

// Factory function to create new instances
function createCounterInstance() {
  return CounterModule;
}