Author Topic: [Paper] OOP Design Pattern: Observer  (Read 4921 times)

0 Members and 1 Guest are viewing this topic.

Offline Deque

  • P.I.N.N.
  • Global Moderator
  • Overlord
  • *
  • Posts: 1203
  • Cookies: 518
  • Programmer, Malware Analyst
    • View Profile
[Paper] OOP Design Pattern: Observer
« on: March 09, 2013, 07:25:51 pm »
Observer

Our example this time is a card playing game that also shows statistics to test the newly created AI (this is not unrealistic, I have made such a thing for robot football). The results shall be shown during the game by several windows containing charts and tables of different types and data. The statistics can also be turned off.
               
Code: [Select]
              points display
                  ^
                  |
                  |
card table <--  state --> chart A
                  |
                  |
                  v
                chart B

This means everytime the state of the game has changed, there are lots of objects that have to be updated. In our example this is the GUI which shows the card table itself, so the player sees what is going on. But there are also several windows with statistics and a display showing the points a player got. The state of the game changes either because a human player made a move or the AI.

The first try

The first approach that comes into your mind may be this (pseudocode):

Code: [Select]
class PointsDisplay {
   
   attribute GameState gameState;

   method testForUpdate() {
      every second do {
         if(gameState.hasStateChanged()){
            displayPoints(gameState.getPoints());
         }
      }
   }

}

ChartA, ChartB and CardTable do something similar.

This is pretty bad for performance, because a lot of classes do needless calles to check whether the state has changed.
This goes hand in hand with synchronization issues.

The second try

This time we do it the other way around. The object that changes the state has to call the update methods of every view component.

Code: [Select]
class AI {

  method nextMove(){
     Card card = takeCard();
     updateChartA(card);
     updateChartB(card);
     updateCardTable(card);
     updatePointsDisplay(card);
  }

}

class CardTable { //This is the gui that shows data, but also
                  //retrieves input of the human player

  method playersHasChosenCard(Card card){
     updateChartA(card);
     updateChartB(card);
     updateCardTable(card);
     updatePointsDisplay(card);
  }

}

Now everytime we add a new way to change the data (i.e. another AI), we also need to add a huge list of method calls that update everything. And if there is a new chart or table that has to be updated, we have to add an update for it everywhere in the program. The problem is that the updates are called in different locations of the code. Forgetting one location is likely. It is a better approach to have this sorted somehow.

The third try

Since the last solution is not appropriate we try a new one. Instead of updating everything in different locations we put it entirely into the GameState itself. This means we need an instance of every object that has to be updated.

Code: [Select]
class GameState {
   
  attribute ChartA chartA;
  attribute ChartB chartB;
  attribute PointsDisplay points;
  attribute CardTable table;

  method update(){
    chartA.update(updateInfo);
    chartB.update(updateInfo);
    points.update(updateInfo);
    table.update(updateInfo);
  }

}

This is much better. There is only one location we need to change when we add a new chart. But it is still not perfect. The list of attributes (and thus also update-calls) may grow a lot. Also we said that we wanted to show only the statistics the user chose to. There is no need in updating charts that are not available right now. We would have to do something like this:

Code: [Select]
class GameState {
   
  attribute ChartA chartA;
  attribute ChartB chartB;
  attribute PointsDisplay points;
  attribute CardTable table;

  method update(){
    if(chartA.isAvailable()) {
       chartA.update(updateInfo);
    }
    if(chartB.isAvailable()) {
       chartB.update(updateInfo);
    }

    points.update(updateInfo);
    table.update(updateInfo);
  }

}

This is where the observer pattern comes into play.

The Observer pattern

This is the UML diagram for the Observer pattern:



Now the GameState notifys all observers when its data has changed. You can imagine this like setting the option to get an e-mail-notification everytime someone has send you a PM on EZ. When you see the e-mail you will know that you have to update yourself by logging into the forum and reading the PM.
To notify every Observer the GameState has a collection of them. The notify()-method will look like this:

Code: [Select]
class GameState {
   
  attribute ObserverCollection observers; 

  method notify(){
    foreach Observer o in observers {
       o.update();
    }
  }

}

The update()-method of an Observer could be implemented like this:

Code: [Select]
class PointsDisplay extends Observer {
   
   attribute GameState gameState;

   method update() {
      State state = gameState.getState();
      displayPoints(state.getPoints());
   }

}

If the user doesn't want to show some charts, the removeObserver-method() is called. We have no unnessecary if-statements anymore to check whether an update is required. The code is reduced to a minimum and easily extendable.

Design principle 3: Aim at a loosely coupled design for interacting objects.

Deque

Offline Kulverstukas

  • Administrator
  • Zeus
  • *
  • Posts: 6627
  • Cookies: 542
  • Fascist dictator
    • View Profile
    • My blog
Re: [Paper] OOP Design Pattern: Observer
« Reply #1 on: March 09, 2013, 08:29:21 pm »
so you have that book as well?  ^^ hehe it's a nice book, has all kinds of weird and useful design patterns.

Offline DaNePaLI

  • Peasant
  • *
  • Posts: 55
  • Cookies: 12
  • Forever n00b
    • View Profile
Re: [Paper] OOP Design Pattern: Observer
« Reply #2 on: March 09, 2013, 09:06:12 pm »
Thanks for the great paper on the Observer design pattern :) . I have not much played with design patterns but I know these are essential stuffs that the software engineering teams need to keep on implementing frequently.

Based on my understanding, we use observer pattern to notify all the depending objects when the state(s) of an object change (one to many). The example that hit my mind is the GUI system where change in background data needs to change the state of one or more GUI items.

Also, what do you think of having abstract GameState class with addObserver(), removeObserver(), and notify() as the base methods, and concrete classes that inherit GameState class and has additional methods getState() and setState(). I mean this could be useful in some scenarios.

And, How can we handle the situation where we need to send notification to yet another object when a state change in some object affects the observer object in some particular fashion.

Great paper. +1

Offline Deque

  • P.I.N.N.
  • Global Moderator
  • Overlord
  • *
  • Posts: 1203
  • Cookies: 518
  • Programmer, Malware Analyst
    • View Profile
Re: [Paper] OOP Design Pattern: Observer
« Reply #3 on: March 10, 2013, 04:36:18 pm »
so you have that book as well?  ^^ hehe it's a nice book, has all kinds of weird and useful design patterns.

Which book?
I used my study notes from university for these papers (I guess I mentioned it in the last paper). I possess only one book about design patterns that I can highly recommend. It is from the so called gang of four who invented those patterns: https://en.wikipedia.org/wiki/Design_Patterns

@DaNePaLI: Thank you.

Also, what do you think of having abstract GameState class with addObserver(), removeObserver(), and notify() as the base methods, and concrete classes that inherit GameState class and has additional methods getState() and setState(). I mean this could be useful in some scenarios.

Of course it can be useful.
Instead of getState(), setState() you might as well provide the changed property or state within notify() as parameter instead (i.e. notify(state)).
Those UML diagrams are just concepts, that you can vary so it suits best for your special situation.

And, How can we handle the situation where we need to send notification to yet another object when a state change in some object affects the observer object in some particular fashion.

Do you have an example?
Because what you can do depends on the concrete problem.

Offline Kulverstukas

  • Administrator
  • Zeus
  • *
  • Posts: 6627
  • Cookies: 542
  • Fascist dictator
    • View Profile
    • My blog
Re: [Paper] OOP Design Pattern: Observer
« Reply #4 on: March 10, 2013, 05:21:07 pm »
Which book?
I used my study notes from university for these papers (I guess I mentioned it in the last paper). I possess only one book about design patterns that I can highly recommend. It is from the so called gang of four who invented those patterns: https://en.wikipedia.org/wiki/Design_Patterns
Yeah, that book :)