Today, in part 4 of my series on OOP programming, I would like to introduce the Observer pattern.
Why Use It?
I think it is absolutely great when I create a class and I find out I can use in different applications. After all, that's one of the reasons to use Object Orientation. One of the main problems that prevents a lot of reuse is tight binding between classes. Tight binding means that one class has to know about another class in order to function. This is not necessarily a Bad Thing, but it becomes one as soon as this knowledge of other classes is tied to a single application.
A good example of what I unfortunately did in the past is binding between Functionality and the User Interface. When I'm developing something, I like to see what's going on inside my objects. So I usually make a simple UI that displays all sorts of information like number of faces/vertices, timing profile, memory-usage, fps etc. This often resulted in either my functional class (e.g. 3D-engine) having to know about UI-elements, or my UI-class containing functionality that should really be in the 3D-engine class. Both cases prevent reuse because the Functionality needs the UI to function properly, and a UI is very application specific.
The Observer pattern allows an object to let other objects know about its internal values without knowing anything specific about the classes of these other objects.
How To Do It
Observer uses inheritance to achieve its goal. The first thing to do is to create two base-classes, which I dubbed TEventServer and TEventClient (You can see I use a Borland compiler :) ). These classes look something like this:
The class containing the functionality of your fancy 3D-engine derives from TEventServer. The UI displaying all sorts of interesting information about the engine is derived from TEventClient and implements the ParameterUpdate function. The UI Attaches itself to the engine by calling Attach(this). In the ParameterUpdate function of the UI, it finds out about the values of parameters/variables of the engine it wishes to display and updates its labels/edit-boxes/statics etc.
How To Improve It
The classes I showed above do the job, but pretty na´ve. For instance, if your server exposes a hundred variables you have to update all hundred of them in the UI for every Update. This is because the Clients have no way of knowing which parameters need to be updated. There are several ways to improve on this. One way I have seen is to give each parameter a text-name, and pass this name as a parameter to the Update method. This goes something like this:
In the server:
In the server:
Another possible improvement is to implement the "push"-model. As you can see, in the implementation I gave, the client (e.g. UI) is responsible for getting the necessary information it wants to display. The push model means the server passes information about what changed and what the new values are. There are several advantages to this method, but there is again a performance penalty because a lot more data is transferred between functions.
Observer can reduce tight binding of classes, thereby reducing tight binding, and offers an interesting approach in situations where some kind of "many-to-one" relationship is desirable. This can go beyond a simple mechanism to inform others about internal the values of an object. Observer can be the basis for an elaborate event-driven system, similar to the windows event-system, where objects attach to multiple servers and respond to a variety of different kinds of events, ranging from user-input to network-activity.
As always, any feedback is appreciated (Well, as long as it's positive anyway :-) ).
By the way, on a totally unrelated note: Is anyone interested in setting up a flipCode Q3A contest/tournament? Would be a lot of fun, I think.
Download The Sample Program: ManicMotion.exe