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 interface with an execute method.
      • Create concrete command classes (LightOnCommand, LightOffCommand) that implement this interface 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 interface or base 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

Here is the complete code for implementing the Command pattern:

from abc import ABC, abstractmethod

# Define the Command interface
class Command(ABC):
    @abstractmethod
    def execute(self):
        pass

# Concrete command classes for turning the light on and off
class LightOnCommand(Command):
    def __init__(self, light):
        self.light = light

    def execute(self):
        self.light.turn_on()

class LightOffCommand(Command):
    def __init__(self, light):
        self.light = light

    def execute(self):
        self.light.turn_off()

# Receiver class encapsulating the light functionalities
class Light:
    def turn_on(self):
        print("The light is on")

    def turn_off(self):
        print("The light is off")

# Invoker class to store and execute commands
class RemoteControl:
    def __init__(self):
        self.slots = {}

    def set_command(self, command_name, command):
        self.slots[command_name] = command

    def press_button(self, command_name):
        if command_name in self.slots:
            self.slots[command_name].execute()
        else:
            print(f"No command found for {command_name}")

# Example of setting up and using the command pattern
if __name__ == "__main__":
    living_room_light = Light()

    light_on_command = LightOnCommand(living_room_light)
    light_off_command = LightOffCommand(living_room_light)

    remote_control = RemoteControl()

    remote_control.set_command("light_on", light_on_command)
    remote_control.set_command("light_off", light_off_command)

    remote_control.press_button("light_on")  # Expected Output: The light is on
    remote_control.press_button("light_off") # Expected Output: The light is off
Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal