Applying Observer and Strategy Patterns for Smart Home Security System and Climate Control

This unit focuses on two design patterns: Observer and Strategy. We'll use these patterns to enable responsive security and flexible climate control in our smart home system.

Quick Summary
  1. Observer Pattern:

    • Purpose: Allows an object (observer) to watch another (subject) and get notified of changes.
    • Steps:
      • Define a Subject with registration, unregistration, and notification methods (e.g., for a SecuritySystem).
      • Implement observers that react to changes (e.g., SecurityApp, SecurityLight).
  2. Strategy Pattern:

    • Purpose: Defines a family of algorithms and makes them interchangeable.
    • Steps:
      • Define a strategy interface with a method for the desired behavior (e.g., TemperatureControlStrategy for controlling temperature).
      • Implement specific strategies with concrete behavior (e.g., HeatingStrategy, CoolingStrategy).
      • Create a context to use and switch strategies (e.g., a ClimateControl system).
Implementing the Observer Pattern for the Security System

Here is the complete code to implement the Observer pattern using JavaScript:

// Define the Subject class
class Subject {
    constructor() {
        this._observers = [];
    }

    registerObserver(observer) {
        this._observers.push(observer);
    }

    unregisterObserver(observer) {
        this._observers = this._observers.filter(obs => obs !== observer);
    }

    notifyObservers() {
        this._observers.forEach(observer => observer.update(this));
    }
}

// Define the SecuritySystem class
class SecuritySystem extends Subject {
    constructor() {
        super();
        this._state = null;
    }

    setState(state) {
        this._state = state;
        this.notifyObservers();
    }
    
    getState() {
        return this._state;
    }
}

// Define the Observer interface
class Observer {
    update(subject) {
        throw new Error('Observer update method must be implemented.');
    }
}

// Implement the SecurityApp observer
class SecurityApp extends Observer {
    update(subject) {
        if (subject instanceof SecuritySystem) {
            console.log(`SecurityApp notified. New state: ${subject.getState()}`);
        }
    }
}

// Implement the SecurityLight observer
class SecurityLight extends Observer {
    update(subject) {
        if (subject instanceof SecuritySystem) {
            console.log(`SecurityLight activated! State: ${subject.getState()}`);
        }
    }
}

// Example usage
const securitySystem = new SecuritySystem();
const app = new SecurityApp();
const light = new SecurityLight();
securitySystem.registerObserver(app);
securitySystem.registerObserver(light);
securitySystem.setState("Intrusion Detected");

// Expected Output:
// SecurityApp notified. New state: Intrusion Detected
// SecurityLight activated! State: Intrusion Detected

The securitySystem instance notifies both SecurityApp and SecurityLight when the state changes to "Intrusion Detected."

Implementing the Strategy Pattern for Climate Control

Here is the complete code to implement the Strategy pattern using JavaScript:

// Define the TemperatureControlStrategy interface
class TemperatureControlStrategy {
    controlTemperature(temperature) {
        throw new Error('TemperatureControlStrategy method must be implemented.');
    }
}

// Implement the HeatingStrategy
class HeatingStrategy extends TemperatureControlStrategy {
    controlTemperature(temperature) {
        console.log(`Heating to ${temperature} degrees.`);
    }
}

// Implement the CoolingStrategy
class CoolingStrategy extends TemperatureControlStrategy {
    controlTemperature(temperature) {
        console.log(`Cooling to ${temperature} degrees.`);
    }
}

// Define the ClimateControl context
class ClimateControl {
    constructor(strategy) {
        this._strategy = strategy;
    }

    setStrategy(strategy) {
        this._strategy = strategy;
    }
    
    controlTemperature(temperature) {
        this._strategy.controlTemperature(temperature);
    }
}

// Example usage
const climateControl = new ClimateControl(new HeatingStrategy());
climateControl.controlTemperature(22); // Expected Output: Heating to 22 degrees.

climateControl.setStrategy(new CoolingStrategy());
climateControl.controlTemperature(18); // Expected Output: Cooling to 18 degrees.

The ClimateControl instance can switch between HeatingStrategy and CoolingStrategy to control the temperature accordingly.

By using the Observer and Strategy patterns, we enhance our smart home system's adaptability and functionality, allowing for responsive security alerts and flexible climate control.

Conclustion

By implementing the Observer and Strategy patterns, our smart home system becomes more robust and versatile. The Observer pattern ensures that our security system is responsive by notifying observers of changes, while the Strategy pattern provides flexibility to our climate control system by allowing different temperature control strategies to be used interchangeably. This combination leads to a more adaptable and efficient smart home environment.

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