event handling in java: alternatives and patterns raja sooriamurthi information systems department...
TRANSCRIPT
Event Handling in Java: Alternatives and Patterns
Raja Sooriamurthi
www.kelley.iu.edu/raja
Information Systems DepartmentKelley School of Business
Indiana University, Bloomington
Portions of this talk are from my presentation Prelude to the Java Event Model given at the 6th annual conference on Innovation and Technology in Computer Science Education (ITiCSE), June 2001, Canterbury, UK.
Concepts
• Event handling
• Event handling models
• Inheritance vs delegation based models
• Notion of first class values
• Use of interfaces
• Callback methods
• Observable / Observer pattern
Learning is finding out what you already know.
--- Richard Bach
Event Handling
event sourceevent
listener
event object
event listener
event listener
Event Handling Models
• Giant Case Statement MS Windows, X-Windows
• Object Oriented Models
– Inheritance based MFC, Motif, Java 1.0– Delegation based Java 1.1
Giant Case Statement
case event of KEY_PRESS: action_1 MOUSE_CLICK: action_2 …end
• Extension => need to edit code
• No hierarchy of events
Problems:
Anatomy of a Button Object
label
color
handle code
Inheritance Based Event Model (Java 1.0)
class Button { // other state information and behavior // ... text // ... color // ... parent widget
boolean handleEvent() { System.out.println( "button has been clicked" ) ; return true; }}
class Start extends Button { boolean handleEvent() { System.out.print( "Start ... " ) ; return super.handleEvent(); }}
Button
Start
Restrictions of the 1.0 Model
• Can not change the behavior of the start button at run-time. The inheritance chain is static.
• Computationally expensive.
• The action is being associated with the button. Should be associated with the application.
• Lots of classes needed.
Delegation Based Event Handling (Java 1.1 +)
• First Class Values
• Callback functions
Key Concepts:
First Class Values
• store in a variable
• pass to a function
• return from a function
Can …
?ff
Examples of First Class Values
• Pascal
• C
• Lisp
• Scheme, Ruby
• Java
scalar types (integer, real, char, boolean)
arrays and records are not
structs
functions
continuations
objects
methods are not first class (research systems like GJ and Pizza )
A Simple Example
// count the positive numbers in an array
class F { static int countPositive( int[] a )
{
int cnt = 0;
for (int i=0; i < a.length; i++)
if ( a[i] > 0 ) cnt ++;
return cnt;
} }
Usage: F.countPositive( x )
3 -657-2 0 0-894 2 5 1X =
The Flexibility of First Class Objects class F { static int countIf( int[] a, Predicate pred )
{ int cnt = 0; for (int i=0; i < a.length; i++) if (pred.test( a[i] )) cnt ++; return cnt; } }
class Predicate { public boolean test( int n ) { return( n > 0 ); } }
Usage: F.countIf(b, new Predicate() );
Abstracting Once More class F { static int countIf( int[] a, Predicate pred ) {
int cnt = 0; for (int i=0; i < a.length; i++) if (pred.test( a[i]) ) cnt ++; return cnt; } }
class Predicate {
public boolean test( int n ) { ? }
}
class IsPositive extends Predicate { public boolean test( int n ) { return( n > 0 );
} }
interface Predicate { boolean test( int n );
}
class IsPositive implements Predicate
{
public boolean test( int n ) { return( n > 0 );
}
}
Better Design with an Interface
Predicate
IsPositive IsPrime …
Use of Anonymous Classes
int[] a = { -4, -2, 0, 1, 3, 5, 7 };
int n1, n2;
n1 = F.countIf( a, new IsPositive() );
// testing for -ve numbers with an anonymous class
n2 = F.countIf( a, new Predicate() {
public boolean test( int n ) {
return( n<0 );
}
}
);
Event Handling with Callbacks
ObservableObserver
1. Observers register themselves with each observable item they are interested in
2. Observables inform each interested observer when a relevant change occurs
Callback Methods
investor = new Investor( "Bob" );
// each investor defines a call back method
void on_change( Stock stk ) { System.out.println( "Price of " + stk ); if (stk.price < 10.00) { System.out.println (" ... falls below 10.00 ... sell"); } }
stk = new Stock( "ABC", 12.50 ); // register an investor
stk.add_watch( investor );
// when a stock price changes ...
stk.percentChange( -10.5 ); // falls by 10.5 %
// ... the stock notifies the interested investors
void percentChange( double change ) {
price += price * (change/100.0);
notifyInvestors();
}
// the book keeping code is simple
private Vector handlers = new Vector();
void add_watch( Investor p ){ handlers.add( p ); }
void notifyInvestors() {
for( int i=0; i<handlers.size(); i++ )
((Investor) handlers.get(i)).on_change( this );
}
Callback Methods (contd.)
class Stock extends Observable { ... void percentChange (double change) { price += price*(change/100.0); setChanged(); notifyObservers(); } }
class Investor implements Observer { ... public void update (Observable s, Object ignore){ Stock stk = (Stock) s; ... } } stk.addObserver ( ... )
Observable / Observer Design Pattern
Summary
• Ubiquity of event driven programming
• Models of event handling– Big switch statement– Inheritance based– Delegation based
• Some design patterns