Example Observer Application: Traffic Lights

This is the post where you have all been waiting for (I hope J), after reading the informative post what an Observer Pattern is. If you have no idea what an observer is, you better start reading my previous theoretical post about the Observer Pattern.

First an overview of the application we are going to build in this post:

  • An application to create a traffic light who changes his colour
  • Easy expandable
  • Future equipped (easy to add changes)
  • Object Oriented
  • With the Observer Pattern

Stage 1: our Model Control View

ControlModelView
Program.cs
TrafficLightApp.cs
Observable.csIObserver.cs
TrafficLights.cs
Light.cs
StartView.cs
Crossing.cs

Program.cs: The start file from the program. It creates a TrafficLightApp Object.
TrafficLightApp.cs: The main control of our program. This class covers for all the interactions. It also starts the views.

Observable.cs: This is the file where every model that needs to be observable will inherit from.
IObserver.cs: An interface where everything that listens to our Observable needs to implement.
TrafficLight.cs: Contains 4 lights (like on a crossroad).
Lights.cs: 1 light.

StartView.cs: A window forms class that has a button to create a new crossing.
Crossing.cs: Enables you to see a crossing with 4 lights.

Stage 2: Implementing the Observable and IObserver

The observable.cs should look like the following:

namespace ObserverExample {
  class Observable {
    private List allObservers = new List();

    public void notifyObservers(){
      foreach (IObserver o in allObservers)
      {
        o.Update(this);
      }
    }

    public void addObserver(IObserver o) {
      allObservers.Add(o);
    }

    public void removeObserver(IObserver o) {
      allObservers.Remove(o);
    }
  }
}

So basically, this class (Observable.cs) holds a list from Interfaces. When the notifyObservers() method is triggered, it accesses the method the method of all the interfaces.

So maybe, the IObserver.cs (interface) might like interesting for you to:

namespace ObserverExample {
  interface IObserver {
    void Update(Observable o);
  }
}

Stage 3: Implementing the rest of the model

TrafficLights.cs and Light.cs, I will not show code extracts from them here, instead you are able (see bottom of the page) to download a zip file with the project included. You can check them there. Simple explanation what they are about? Light is just 1 light, and has a status which reflects the colour the lamp has (Red, orange or green). Each Light also has a changeLight method what changes the current colour to the next.

TrafficLights has a collection or list<> from 4 Lights. It has a method to change all the 4 their (colour) states. This class is also Observable, so it extends Observable.

Stage 4: Completing the control

I already (from the beginning) did some changes. I edited the Program.cs, to this:

static class Program {
  [STAThread]
  static void Main() {
    TrafficLightApp Tla = new TrafficLightApp();
    Tla.ExecuteProgram();
  }
}

The TrafficLightApp() starts our StartView and also starts new windows, does the ‘control’, the hard work, makes it all works. If you wan’t to see this code, again, download the zip (at the bottom of this page).

Stage 5: Implementing the view

StartView.cs

I just created a really simple interface, with a button that enables to add a new crossing (That has 4 lights, and the ability to change the state). It looks like what you see at the right of this page.

namespace ObserverExample {
  public partial class StartView : Form {
    private TrafficLightApp tla;
    public StartView(TrafficLightApp Tla) {
      InitializeComponent();
      tla = Tla;
    }

    private void btnCreateNew_Click(object sender, EventArgs e) {
      tla.addCrossing();
    }
  }
}

Crossing.cs

Each Crossing contains 4 lights, and looks really nice. Pressing the next will change the status in the class light.cs. Then an notifyObserver() get’s done, and this view, wich is an Observer, will update.

Below you will find the most important parts of the code:

Update:

void IObserver.Update(Observable o) {
  Synchronize();
}

Synchronize:

public void Synchronize() {
  pnlPlaceholder.Controls.Clear();
  foreach (Light light in lights) {
    Panel pnl = new Panel();
    pnl.Width = 50;
    pnl.Height = 50;
    switch (light.Status) {
      case 0: pnl.BackColor = Color.Green;
      break;
      case 1: pnl.BackColor = Color.Orange;
      break;
      case 2: pnl.BackColor = Color.Red;
      break;
      case 3: pnl.BackColor = Color.Red;
      break;
    }
    pnlPlaceholder.Controls.Add(pnl);
  }
}

And the construct:

public Crossing(TrafficLights Tl, TrafficLightApp TLA) {
  this.tl = Tl;
  this.tla = TLA;
  lights = new List<Light>();
  lights = Tl.Lights;
  tl.addObserver(this);
  InitializeComponent();
  Synchronize();
}

The magic

The files

You can download the Source Files!

I’ve also created another zip file with the exe, and you can find it on the same link.

Sources

I’ve learned a lot from this in the book Design Patterns from O’Reilly. Also, the idea for this example, I got from my java lessons in Howest Simon Stevin, a high school in Bruges.

3 Replies to “Example Observer Application: Traffic Lights”

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.