Implementing the Observer Pattern: Real-World Example
Observer pattern

Implementing the Observer Pattern: Real-World Example

Definition: The Observer pattern is a behavioral design pattern that fosters a one-to-many relationship between objects. In this pattern, an object, known as the subject, maintains a list of dependent objects, called observers. When the subject's state changes, it notifies all its observers, allowing them to automatically update their state or perform actions in response to the change. The Observer pattern promotes loose coupling between objects, making it a powerful tool for designing flexible and maintainable software systems.

Goal: In the example of a video player class (playing video files), we will implement the Observer pattern. Its role will be to stop all previously played video files. In this way, we prevent the user from playing more than one video at the same time.

This adaptation introduces the idea of referring to another article for a deeper understanding of the code in the example. It mentions the Adapter pattern as a topic of interest for creating the VideoPlayer class.

Adapter pattern: https://medium.com/@predragnastic/how-to-build-a-carousel-8cdbdedfba12

Observer example: https://codesandbox.io/s/observer-99w3f8

index.ts

const videoSubject = new VideoSubject();
const players = document.querySelectorAll(".js-player");

players.forEach((player) => {
  const playerElement = player as HTMLDivElement;
  const { type, videoid } = playerElement.dataset;
  const { id } = playerElement;
  if ((type === "youtube" || type === "vimeo") && videoid && id) {
    if (player) {
      const observer = new VideoObserver({
        type,
        videoId: videoid,
        elementId: id,
        subjectPlay: (videoId) => videoSubject.play(videoId)
      });
      videoSubject.attach(observer);
    }
  }
});        

The idea is for the Observer class (VideoSubject) to inform participants (VideoObservers) about the currently playing video. Each VideoObserver, as a participant, creates a VideoPlayer object, which serves as an adapter class for video playback. We use this approach because we don't want the focus to be on the player type, but rather on having every player behave the same, regardless of its type. Each created observer is added to the VideoSubject through the attach method.

{
  type, 
  videoId: videoid,
  elementId: id,
  subjectPlay: (videoId) => videoSubject.play(videoId)
}        

Each of the players uses a video ID and an element ID for instantiation. The 'type' parameter serves as a means for the adapter class, located in the 'videoPlayer.ts' file, to determine which instance to create. The 'subjectPlay' method is passed to allow different players to use it in different ways. If you navigate to the 'videoPlayerCreator.ts' file, you'll notice that different video players use different methods to inform us whether a video file is currently playing or not. It's beneficial to keep this configuration in one place. Our focus is on the 'play' option for playback and the playback time so that we can track when the video file was played.

In summary, in the first part, when the YouTube or Vimeo play icon is clicked, the players are notified through the Subject method using notify.

YT (YouTube) utilizes the onStateChange event, while Vimeo makes use of the player.on("play", () => {}) event handler.


In some cases, we want to use custom triggers to play a video file. For such occasions, we apply the same logic.

// Custom triggers
const observerList = videoSubject.getObservers();

const triggers = document.querySelectorAll(".js-play-video");
triggers.forEach((button) => {
  const playButton = button as HTMLButtonElement;
  const videoId = playButton.dataset.videoid;
  const observer = observerList.find((observer) => {
    const id = observer.getVideoId();
    return id === videoId;
  });
  if (observer) {
    playButton.addEventListener("click", () => observer.play());
  }
});        

When observer.play() is invoked, it initiates video playback. Through their respective events, YouTube (YT) and Vimeo will trigger the play method from the, which, in turn, notifies other players about which video has been played.

This way, we can add any number of video players, and they will all function in the same manner.

To view or add a comment, sign in

More articles by Predrag Nastić

Others also viewed

Explore content categories