Lesson 3
Building the Smart Home Automation and Lighting System with JavaScript Design Patterns
Building the Smart Home Automation and Lighting System

In this unit, we'll implement two essential design patterns: the Command pattern and the Decorator pattern, aimed at enhancing our smart home automation and lighting system. These patterns help create a more flexible and expandable system for automation and lighting control.

Quick Summary
  1. Command Pattern:

    • Purpose: Encapsulates a request as an object, enabling parameterization, queuing, logging, and support for undoable operations.
    • Steps:
      • Define a command class with an execute method.
      • Create concrete command classes (LightOnCommand, LightOffCommand) that implement this method and perform specific actions.
      • Implement a receiver class (Light) with methods to turn the light on and off.
      • Use an invoker class (RemoteControl) to store and execute commands.
  2. Decorator Pattern:

    • Purpose: Dynamically adds additional functionality to objects without altering their structure.
    • Steps:
      • Define a component class (Light).
      • Create a base decorator class (LightDecorator) that implements the component interface and holds a reference to a component object.
      • Develop concrete decorators (ColorChangeDecorator) to extend functionalities of the basic component.
Implementing the Command Pattern

Using the Command pattern, we define our commands and receivers, then utilize an invoker to store and execute commands. This enables flexible and parameterizable control over our smart home system.

Code Implementation for Command Pattern

Here is the complete code for implementing the Command pattern using JavaScript:

JavaScript
1// Command interface 2class Command { 3 execute() { 4 throw new Error('Execute method must be overridden.'); 5 } 6} 7 8// Concrete command classes for turning the light on and off 9class LightOnCommand extends Command { 10 constructor(light) { 11 super(); 12 this.light = light; 13 } 14 15 execute() { 16 this.light.turnOn(); 17 } 18} 19 20class LightOffCommand extends Command { 21 constructor(light) { 22 super(); 23 this.light = light; 24 } 25 26 execute() { 27 this.light.turnOff(); 28 } 29} 30 31// Receiver class encapsulating the light functionalities 32class Light { 33 turnOn() { 34 console.log("The light is on"); 35 } 36 37 turnOff() { 38 console.log("The light is off"); 39 } 40} 41 42// Invoker class to store and execute commands 43class RemoteControl { 44 constructor() { 45 this.slots = {}; 46 } 47 48 setCommand(commandName, command) { 49 this.slots[commandName] = command; 50 } 51 52 pressButton(commandName) { 53 if (this.slots[commandName]) { 54 this.slots[commandName].execute(); 55 } else { 56 console.log(`No command found for ${commandName}`); 57 } 58 } 59} 60 61// Example of setting up and using the command pattern 62const livingRoomLight = new Light(); 63 64const lightOnCommand = new LightOnCommand(livingRoomLight); 65const lightOffCommand = new LightOffCommand(livingRoomLight); 66 67const remoteControl = new RemoteControl(); 68 69remoteControl.setCommand("light_on", lightOnCommand); 70remoteControl.setCommand("light_off", lightOffCommand); 71 72remoteControl.pressButton("light_on"); // Expected Output: The light is on 73remoteControl.pressButton("light_off"); // Expected Output: The light is off
Implementing the Decorator Pattern

By using the Decorator pattern, we can dynamically enhance our smart home's lighting system with additional features without altering the underlying structure.

Code Implementation for Decorator Pattern

Here is the complete code for implementing the Decorator pattern using JavaScript:

JavaScript
1// Basic Light class 2class Light { 3 operate() { 4 return "Basic light operation"; 5 } 6} 7 8// Base Decorator class 9class LightDecorator extends Light { 10 constructor(decoratedLight) { 11 super(); 12 this.decoratedLight = decoratedLight; 13 } 14 15 operate() { 16 return this.decoratedLight.operate(); 17 } 18} 19 20// Concrete Decorator for adding color-changing functionality 21class ColorChangeDecorator extends LightDecorator { 22 operate() { 23 return `${super.operate()} with color change`; 24 } 25} 26 27// Example of using the decorator pattern 28const basicLight = new Light(); 29console.log(basicLight.operate()); // Expected Output: Basic light operation 30 31const colorLight = new ColorChangeDecorator(basicLight); 32console.log(colorLight.operate()); // Expected Output: Basic light operation with color change

Implementing the Command and Decorator patterns in our smart home system provides flexibility and scalability. The Command pattern encapsulates requests as objects, allowing for parameterizable and undoable operations. The Decorator pattern dynamically adds functionalities, making the system adaptable and extensible.

Summary

In summary, the integration of both Command and Decorator design patterns significantly enhances the functionality and flexibility of a smart home automation and lighting system. By allowing requests to be encapsulated as objects, the Command pattern provides a robust framework for executing, queuing, and undoing actions with ease. Meanwhile, the Decorator pattern affords the ability to extend object functionalities dynamically, supporting ongoing scalability and adaptability without altering existing structures. Together, these patterns contribute to a sophisticated, maintainable, and extensible smart home solution.

Enjoy this lesson? Now it's time to practice with Cosmo!
Practice is how you turn knowledge into actual skills.