Observer pattern in the context of a Game App
Published: 2023-06-13 21:55:04


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ioiofeao9i6ygyush8r4.jpg)

The Observer pattern is a design pattern that allows objects to be notified of changes to the state of another object, called the "subject." In the context of a game app, this could be used to notify different game components (such as scoreboards, health bars, etc.) when the game's state changes (such as when the player collects a power-up or takes damage).

Here's an example TypeScript code snippet that illustrates the Observer pattern in a game app:

```typescript
interface Subject {
  registerObserver(o: Observer): void;
  removeObserver(o: Observer): void;
  notifyObservers(): void;
}

interface Observer {
  update(score: number, health: number): void;
}

class Game implements Subject {
  private score: number = 0;
  private health: number = 100;
  private observers: Observer[] = [];

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

  public removeObserver(o: Observer): void {
    const index = this.observers.indexOf(o);
    if (index !== -1) {
      this.observers.splice(index, 1);
    }
  }

  public notifyObservers(): void {
    for (const observer of this.observers) {
      observer.update(this.score, this.health);
    }
  }

  public collectPowerUp(): void {
    this.score += 10;
    this.notifyObservers();
  }

  public takeDamage(): void {
    this.health -= 10;
    this.notifyObservers();
  }
}

class Scoreboard implements Observer {
  private score: number = 0;

  public update(score: number, health: number): void {
    this.score = score;
    this.render();
  }

  public render(): void {
    console.log(`Score: ${this.score}`);
  }
}

class HealthBar implements Observer {
  private health: number = 100;

  public update(score: number, health: number): void {
    this.health = health;
    this.render();
  }

  public render(): void {
    console.log(`Health: ${this.health}`);
  }
}

// Usage
const game = new Game();
const scoreboard = new Scoreboard();
const healthBar = new HealthBar();

game.registerObserver(scoreboard);
game.registerObserver(healthBar);

game.collectPowerUp(); // Logs "Score: 10"
game.takeDamage(); // Logs "Health: 90"

game.removeObserver(healthBar);
game.collectPowerUp(); // Logs "Score: 20" (only the Scoreboard is notified)

```

In this example, the Game class is the subject, which maintains the state of the game (score and health) and notifies its observers when the state changes. The Scoreboard and HealthBar classes are observers that listen for changes to the game state and update their respective displays accordingly.

When the collectPowerUp method is called on the Game instance, it increases the score and notifies all observers by calling notifyObservers. Similarly, when the takeDamage method is called, it decreases the health and notifies all observers.

The Scoreboard and HealthBar instances both implement the Observer interface, which requires them to have an update method that takes in the current score and health values. When they receive an update from the Game instance, they update their own internal state and call render to update their display.

Finally, we can see that we can remove an observer by calling removeObserver on the Game instance, and the removed observer will no longer be notified of updates.