The Observer Design Pattern as supported by Java

snottybugbearSoftware and s/w Development

Nov 3, 2013 (3 years and 11 months ago)

91 views

The Obser
ver
D
esign Pattern as supported by Java


An
example

of the Observer Design Pattern
wit
h the

simplest

model I can devi
se
. (Note: imports removed)


public

class

SimpleModel
extends

Observable {


private

int

counter
;



public

SimpleModel() {

counter

= 0;

}



public

int

currentCount() {

return

counter
;

}



public

void

increment() {


counter
++;


// Do NOT forget to tell yourself the state has changed


this
.setChanged();


// Otherwise, the next notifyObservers message will not
send update messages to
Observers


this
.notifyObservers();


}

}



//

One
View
that
draw
s

line
s

to represent a

number

||||

for 4 for example

public

class

ViewOne
extends

JPanel
implements

Observer {


private

int

numberOfLinesToDraw
;



public

ViewOne() {


this
.setBackground(Color.
GREEN
);


}



//
T
he 2nd argument

is ign
ored


public

void

update(Observable theNotifier, Object completeFrame) {



// Cast now or later


SimpleModel theModel = (SimpleModel) theNotifier;


numberOfLinesToDraw

= theModel.currentCount();



this
.repaint();



}




public

void

paintComponent(Graphics g) {





super
.paintComponent(g);





int

xPosition = 5;




for

(
int

c

=
1
;
c

<
=

numberOfLinesToDraw
;
c
++) {




g
.drawLine(xPosition, 5, xPosition, 25);




xPosition += 5;




}



}

}



public

class

ViewTwo
extends

JPanel
implements

Observer {


private

String
stringToDrawOnPanel

=
"0"
;



public

ViewTwo() {


this
.setBackground(Color.
YELLOW
);


this
.setFont(
new

Font(
"Courier"
, Font.
BOLD
, 20
));



}





//
T
he 2nd argument

is ign
ored




public

void

update(Observable theNotifier, Object completeFrame) {




SimpleModel theModel = (SimpleModel) theNotifier;



stringToDrawOnPanel

=
""

+ theModel.currentCount();


this
.repaint();


}




public

void

paintComponent(Graphics g) {


super
.paintComponent(g);


g.drawString(
stringToDrawOnPanel
, 4, 24);


}


//

This is the

application
. It contains references to the model and bot
h views.

// This
application

also has an inner class
UpdateButtonListener

as the
C
ontroller

import

java.awt.Container;

import

java.awt.event.ActionEvent;

import

java.awt.event.ActionListener;

import

java.util.Observer;


import

javax.swing.JButton;

import

javax.swing.JFrame;

import

javax.swing.JPanel;


public

class

TwoObserversMain
extends

JFrame {



public

static

void

main(String[] args) {


new

TwoObserversMain().setVisible(
true
);


}



public

TwoObserversMain() {


layoutThisJFrame();


registerListeners();


setUpModelAndObservers();


}



private

SimpleModel
theModel
;



private

JPanel
view1

=
new

ViewOne();
// The views could also be Observer


private

JPanel
view2

=
new

ViewTwo();


private

JPanel
currentView

=
view1
;
// The default Observer


private

JButton
upDateButton

=
new

JButton(
"Increment the model by 1"
);


private

JButton
buttonOne

=
new

JButton(
"View One"
);


private

JButton
buttonTwo

=
new

JButton(
"View Two"
);


//

cp
:
the pl
ace where inner classes can add,
remove
, rep
aint, and validate
layout


private

Container
cp

= getContentPane();



public

void

layoutThisJFrame() {


setTitle(
"Two Observers"
);


setSize(260, 200);


setDefaultClo
seOperation(JFrame.
EXIT_ON_CLOSE
);


setLayout(
null
);


view1
.setSize(222, 30);


view1
.setLocation(10, 60);


view2
.setSize(222, 30);


view2
.setLocation(10, 60);


upDateButton
.setSize(200, 30);


upDateButton
.setLocation(20, 10);


add(
upDateButton
);


cp
.add((JPanel)
currentView
);


// Get two buttons to the bottom


buttonOne
.setSize(100, 30);


buttonOne
.setLocation(10, 100);


buttonTwo
.setSize(100, 30);


buttonTwo
.setLocation(130, 100);


add(
buttonOne
);


add(
buttonTwo
);


}



public

void

setUpModelAndObservers() {


theModel

=
new

SimpleModel();


theModel
.addObserver((Observer)
view1
);


theModel
.addObserver((Observer)
view2
);


}



public

void

registerListeners() {


upDateButton
.addActionListener(
new

UpdateButtonListener());


ChangeViewListener listener =
new

ChangeViewListener();


buttonOne
.addActionListener(listener);


buttonTwo
.addActionListener(listener);


}



// This is a controller in MVC. In general, controllers are implemented in


// Java as a registered listener to a components in the view.


// Notice that this controller interacts with the model.


private

class

UpdateButtonListener
implements

ActionListener {


public

void

actionPerformed(ActionEvent ae) {


theModel
.increment();


}


}



// This
listener
is needed to swap views and update the GUI to


// show the new view. With the current project, you have one


// view, a class like this is not needed.


private

class

ChangeViewListener
implements

ActionListener {


public

void

actionPerformed(ActionEvent ae) {



//
cp

is the object in the JFrame to which add and remove messages


// may be sent. Container
cp

= getContentPane();


cp
.remove
(
currentView
);



JButton buttonJustClicked =
(JButton) ae.getSource()
;



if

(buttonJustClicked ==
buttonOne
)


currentView

=
view1
;



if

(buttonJustClicked ==
buttonTwo
)


currentView

=
view2
;



cp
.add(
currentView
);


// We need both of these refreshes whenever switching views


// because the contentPane (
cp
) doesn't do it automatically and


// the repaint messages in the views is not in play at this second.


cp
.validate();


cp
.repaint();


}


}

}