//
Purpose. Observer design pattern
//
1. Model the "independent" functionality with a "subject"
abstraction
// 2. Model the "dependent" functionality with
"observer" hierarchy
// 3. The Subject is coupled only to the
Observer base class
// 4. Observers register themselves with the
Subject
// 5. The Subject broadcasts events to all registered
Observers
// 6. Observers "pull" the information they need from
the Subject
// 7. Client configures the number and type of Observers
class
Subject { // 1. The
"independent" abs
private Observer[] observers = new Observer[9]; // 3. Coupled to base class
private int totalObs = 0;
private int state;
public void attach( Observer o ) { observers[totalObs++] = o; } // 3.
Coupled
public int getState() { return state; }
public void setState( int in ) {
state = in;
notifyObservers(); }
private void notifyObservers() {
for (int i=0; i < totalObs; i++)
observers[i].update(); // 3. Coupled to base class
} } // 5. Broadcast events to
observers
abstract class Observer { // 2. Root of the "dependent"
hierarchy
protected Subject
subj;
public abstract void
update(); }
class HexObserver extends Observer { // 2. Concrete class of the
"dependent"
public
HexObserver( Subject s ) { // hierarchy
subj = s;
subj.attach( this ); } // 4. Observers register themselves
public void update() {
System.out.print( " " + Integer.toHexString(
subj.getState() ) );
} } // 6.
Observers "pull" information
class OctObserver extends
Observer {
public OctObserver(
Subject s ) {
subj = s; subj.attach( this ); } // 4. Observers
register themselves
public void
update() {
System.out.print(
" " + Integer.toOctalString(
subj.getState() ) );
} } // 6.
Observers "pull" information
class BinObserver extends
Observer {
public BinObserver(
Subject s ) {
subj = s; subj.attach( this ); } // 4. Observers
register themselves
public void
update() {
System.out.print(
" " + Integer.toBinaryString(
subj.getState() ) );
} } // 6.
Observers "pull" information
public class ObserverDemo
{
public static void main(
String[] args ) {
Subject sub
= new Subject();
// 7. Client
configures the number and type of Observers
new HexObserver( sub );
new OctObserver( sub ); new
BinObserver( sub );
while
(true) {
System.out.print(
"\nEnter a number: " );
sub.setState( Read.anInt() );
}
} }
// Enter a
number: 15
// f 17
1111
// Enter a number: 17
// 11 21 10001
// Enter a number: 31
// 1f
37 11111
//
Purpose. Observer design pattern, class
inheritance vs type inheritance
// SensorSystem is the
"subject". Lighting, Gates,
and Surveillance are the
// "views". The subject is only coupled to the "abstraction" of
AlarmListener.
// An object's class defines how the object is
implemented. In contrast, an
//
object's type only refers to its interface.
Class inheritance defines an
// object's implementation in terms of
another object's implementation.
Type
// inheritance describes when an object can be used in place
of another.
// [GOF, pp13-17]
interface AlarmListener { public
void alarm(); }
class SensorSystem {
private java.util.Vector listeners = new
java.util.Vector();
public
void register( AlarmListener al ) { listeners.addElement( al ); }
public void soundTheAlarm() {
for (java.util.Enumeration
e=listeners.elements(); e.hasMoreElements(); )
((AlarmListener)e.nextElement()).alarm();
} }
class Lighting implements
AlarmListener {
public void
alarm() { System.out.println( "lights up" ); }
}
class
Gates implements AlarmListener {
public void alarm() { System.out.println( "gates close" );
}
}
class CheckList {
public void byTheNumbers() { //
Template Method design pattern
localize();
isolate();
identify(); }
protected void localize() {
System.out.println( " establish a perimeter" ); }
protected void isolate() {
System.out.println( "
isolate the grid" ); }
protected void identify() {
System.out.println( "
identify the source" ); }
}
// class inheri. // type inheritance
class Surveillance extends CheckList
implements AlarmListener {
public void alarm() {
System.out.println( "Surveillance - by the numbers:" );
byTheNumbers(); }
protected void isolate() {
System.out.println( " train the
cameras" ); }
}
public class ClassVersusInterface {
public static void main( String[] args )
{
SensorSystem ss = new
SensorSystem();
ss.register(
new Gates() );
ss.register( new Lighting() );
ss.register( new Surveillance() );
ss.soundTheAlarm();
} }
// gates close
// lights
up
// Surveillance - by the numbers:
// establish a perimeter
// train the cameras
//
identify the source