Observer and Strategy Patterns

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 be notified of changes.
    • Steps:
      • Define a Subject class with registration, unregistration, and notification methods (e.g., for a SecuritySystem).
      • Implement observer interfaces or abstract classes 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 or abstract class with a method for the desired behavior (e.g., TemperatureControlStrategy for controlling temperature).
      • Implement specific strategies with concrete behaviors (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 TypeScript:

// Define the Observer interface
interface Observer {
    update(subject: Subject): void;
}

// Define the Subject class
class Subject {
    private observers: Observer[] = [];

    public registerObserver(observer: Observer): void {
        this.observers.push(observer);
    }

    public unregisterObserver(observer: Observer): void {
        this.observers = this.observers.filter(obs => obs !== observer);
    }

    protected notifyObservers(): void {
        for (const observer of this.observers) {
            observer.update(this);
        }
    }
}

// Define the SecuritySystem class
class SecuritySystem extends Subject {
    private state: string | null = null;

    public setState(state: string): void {
        this.state = state;
        this.notifyObservers();
    }
    
    public getState(): string | null {
        return this.state;
    }
}

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

// Implement the SecurityLight observer
class SecurityLight implements Observer {
    public update(subject: Subject): void {
        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."

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