The fact that control is handed over to
the environment has, however, also some disadvantages.
First of all, as experience with student assignments shows,
it is difficult to learn in the beginning.
But even when mastered, applications may be hard
to debug, since it is not always clear why a particular handler
was invoked, and because it may be difficult to repeat
the computation preceding the fault.
Applicability
Some variant of the reactor pattern is
used in Unix (X) Windows, (MS) Windows, and also GUI libraries
such as Interviews, ET++ and hush.
Another example is the Orbacus object request broker, that
supports a reactor mode for
server objects, which allows for receiving messages
from multiple sources in a single thread.
The Orbacus broker, however, also allows for multi-threaded
servers.
Abstract event systems
To conclude this chapter about idioms and patterns,
we will look at a somewhat more detailed example
employing (user-defined) events to characterize
and control the interaction between the objects.
The example is taken from [Henderson93].
The abstract system, or repertoire of
statements indicating
the functionality of our application
is depicted in slide [as-system].
th = new centigrade();
th = new fahrenheit();
th.set(f);
f = th.get();
For thermometer th, th1; float f;
slide: Abstract system -- thermometers
First, we will define the functional behavior
of the system (in this case a collection of thermometers
that record and display temperature values, as characterized above).
Then we will introduce the user interface classes, respectively
to update the temperature value of a thermometer
and to display its value.
After that we define a concrete event class
(derived from an abstract event class) for each of the
possible kinds of interactions that may occur.
Then, after installing the actual objects comprising
the system, we will define the dependencies
between (actual) events, so that we can guarantee
that interactions with the user will not result
in an inconsistent state.
Functional behavior
A thermometer must provide the means to store
a temperature value and allow for the changing
and retrieving of this value.
The temperature values are assumed to be stored
in degrees Kelvin.
class thermometer { thermometer
protected thermometer( float v ) { temp = v; }
public void set(float v) { temp = v; }
public float get() { return temp; }
protected float temp;
};
Since only derived classes can use the
protected constructor, no direct instances
of thermometer exist, so the class is abstract.
We will distinguish between two kinds of thermometers,
measuring temperatures respectively in centigrade
and fahrenheit.
class centigrade extends thermometer { centigrade
public centigrade() { super(0); }
public void set(float v) { temp = v + 273; }
public float get() { return temp - 273; }
};
The class centigrade redefines the methods get and set
according to the measurement in centigrade,
and in a similar way we may define the class
fahrenheit.
class fahrenheit extends thermometer { fahrenheit
public fahrenheit() { super(0); }
public void set(float v) { temp = (v - 32) * 5/9 + 273; }
public float get() { return temp * 9/5 + 32 - 273; }
};
Both the thermometer realization classes take care
of performing the conversions necessary
to store and retrieve the absolute temperature value.
User interface
We will define two simple interface classes, of which we
omit the implementation details.
First, we define the interface of the displayer
class, needed to put values to the screen.
class displayer extends window { displayer
public displayer() { ... }
public void put(String s) { ... }
public void put(float f) { ... }
};
And secondly, we define a prompter class,
which defines (in an abstract way)
how we may get a value from the user
(or some other component of the system).
class prompter extends window { prompter
public prompter(String text) { ... }
public float get() { ... }
public String gets() { ... }
};
Together, the classes displayer and prompter
define a rudimentary interface which is sufficient
to take care of many of the interactions between
the user and the system.
Events
To define the interactions with the user
(and their possible consequences) we will
employ events, that is instances of realizations
of the abstract event class, defined below.
abstract class event { event
pubic void dependent(event e) { ... }
pubic void process() { ... }
public void operator(); // abstract method
private event[] dep;
};
Since a simple event (for example, the modification of a value)
may result in a series of events
(needed to keep the system in a consistent state),
an event object maintains a set of dependent events,
which may be activated using the process method.
Further, each class derived from event is assumed
to define the application operator, that is the actual
actions resulting from activating the event.
The first realization of the abstract event class
is the update event class,
which corresponds to retrieving a new
temperature value from the user.
class update extends event { update
public update(thermometer th, prompter p) {
_th =th; _p = p;
}
void operator()() {
_th.set( _p.get() );
process();
}
thermometer _th;
prompter _p;
};
An update involves a thermometer and a prompter,
which are stored when creating the update event object.
Activating an update event instance results
in retrieving a value from the prompter,
setting the thermometer to this value and
activating the dependent events.
In a similar way, we define the second realization
of the abstract event class, the show event class,
which corresponds to displaying
the value of a thermometer.
class show extends event { show
public show(thermometer th, displayer d) {
_th = th; _d = d;
}
public void operator() {
_d.put( _th.get() );
process();
}
thermometer _th;
displayer _d;
};
Activating a show event instance results in retrieving
a value from the thermometer,
putting that value on display and activating the
events associated with this event.
The installation
The next step we must take is to install the
application, that is to create the objects comprising
the functional behavior of the system,
the user interface objects and (finally)
the various event objects.
thermometer c = new centigrade();
thermometer f = new fahrenheit();
displayer cd = new displayer("centigrade");
displayer fd = new displayer("fahrenheit");
prompter cp = new prompter("enter centigrade value");
prompter fp = new prompter("enter fahrenheit value");
show sc = new show(c,cd);
show sf = new show(f,fd);
update uc = new update(c,cp);
update uf = new update(f,fp);
Having created the objects, we are almost done.
The most important and perhaps difficult part
is to define the appropriate dependencies
between the respective event objects.
uc.dependent(sc);
uc.dependent(sf);
uf.dependent(sc);
uf.dependent(sf);
As shown above, we declare the event of showing
the value of the centigrade thermometer
(and also of the fahrenheit thermometer)
to be dependent upon the event of updating the value of
the centigrade thermometer.
And we repeat this declaration for the event
of updating the value of the fahrenheit thermometer.
We may now allow the user the choice between updating
the centigrade or fahrenheit thermometer temperature value,
for example by inserting these events in a menu,
as indicated below
menu.insert(uc);
menu.insert(uf);
The reader is urged to do some mental processing
to check that updating the value of one thermometer
actually results in changing the value displayed
for the other thermometer as well.
Discussion
Organizing interactions with the user
(and the other components of the system as well)
by means of events provides a powerful way in which
to control the consequences of one
particular (kind of) interaction.
The advantage of such an approach is that
the repertoire of possible interactions
can easily be extended or modified
without affecting the other parts of the system
(the parts realizing the functional behavior of the
system and the particularities of the user interface).
From the perspective of design, it is a good alternative
for defining {\em behavioral
compositions} (and its corresponding protocol
of interaction) in a more or less formal way.
See also section [Cooperation].
(C) Æliens
04/09/2009
You may not copy or print any of this material without explicit permission of the author or the publisher.
In case of other copyright issues, contact the author.