Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Applied Java™ Patterns - Stephen Stelting, Olav Maassen.pdf
Скачиваний:
198
Добавлен:
24.05.2014
Размер:
2.84 Mб
Скачать

Observer

In the Observer example, an observer sends updates about the state of a Task to all registered listeners in a GUI.

It's important to recognize that any Java GUI code normally uses the Observer pattern for event handling. When you write a class that implements a listener interface like ActionListener, you are creating an observer. Registering that listener with a component through the method addActionListener associates the observer with an observable element, the Java GUI component.

In this example, the observable element is represented by the Task being modified in the GUI. The class

TaskChangeObservable keeps track of the listeners for changes to the Task through the methods

addTaskChangeObserver and removeTaskChangeObserver.

Example A.89 TaskChangeObservable.java

1.import java.util.ArrayList;

2.import java.util.Iterator;

3.public class TaskChangeObservable{

4.private ArrayList observers = new ArrayList();

6.public void addTaskChangeObserver(TaskChangeObserver observer){

7.if (!observers.contains(observer)){

8. observers.add(observer);

9.}

10.}

11.public void removeTaskChangeObserver(TaskChangeObserver observer){

12.observers.remove(observer);

13.}

14.

15.public void selectTask(Task task){

16.Iterator elements = observers.iterator();

17.while (elements.hasNext()){

18. ((TaskChangeObserver)elements.next()).taskSelected(task);

19.}

20.}

21.public void addTask(Task task){

22.Iterator elements = observers.iterator();

23.while (elements.hasNext()){

24. ((TaskChangeObserver)elements.next()).taskAdded(task);

25.}

26.}

27.public void updateTask(Task task){

28.Iterator elements = observers.iterator();

29.while (elements.hasNext()){

30. ((TaskChangeObserver)elements.next()).taskChanged(task);

31.}

32.}

33.}

TaskChangeObservable has the business methods selectTask, updateTask, and addTask. These methods send

notifications of any changes to a Task.

Every observer must implement the TaskChangeObserver interface, allowing the TaskChangeObservable to call the appropriate method on each observer. If a client were to call the method addTask on the TaskChangeObservable, for instance, the observable object would iterate through its observers and call the taskAdded method on each.

Example A.90 TaskChangeObserver.java

1.public interface TaskChangeObserver{

2.public void taskAdded(Task task);

3.public void taskChanged(Task task);

4.public void taskSelected(Task task);

5.}

The class ObserverGui provides a GUI in this demonstration, and creates a TaskChangeObservable object. In addition, it creates three panels that implement the TaskChangeObserver interface, and matches them with the TaskChangeObservable object. By doing this, the TaskChangeObservable is able to effectively send updates among the three panels of the GUI.

266

Example A.91 ObserverGui.java

1.import java.awt.Container;

2.import java.awt.event.WindowAdapter;

3.import java.awt.event.WindowEvent;

4.import javax.swing.BoxLayout;

5.import javax.swing.JFrame;

6.public class ObserverGui{

7.public void createGui(){

8.JFrame mainFrame = new JFrame("Observer Pattern Example");

9.Container content = mainFrame.getContentPane();

10.content.setLayout(new BoxLayout(content, BoxLayout.Y_AXIS));

11.TaskChangeObservable observable = new TaskChangeObservable();

12.TaskSelectorPanel select = new TaskSelectorPanel(observable);

13.TaskHistoryPanel history = new TaskHistoryPanel();

14.TaskEditorPanel edit = new TaskEditorPanel(observable);

15.observable.addTaskChangeObserver(select);

16.observable.addTaskChangeObserver(history);

17.observable.addTaskChangeObserver(edit);

18.observable.addTask(new Task());

19.content.add(select);

20.content.add(history);

21.content.add(edit);

22.mainFrame.addWindowListener(new WindowCloseManager());

23.mainFrame.pack();

24.mainFrame.setVisible(true);

25.}

26.

27.private class WindowCloseManager extends WindowAdapter{

28.public void windowClosing(WindowEvent evt){

29. System.exit(0);

30.}

31.}

32.}

Example A.92 TaskEditorPanel.java

1.import java.awt.BorderLayout;

2.import javax.swing.JPanel;

3.import javax.swing.JLabel;

4.import javax.swing.JTextField;

5.import javax.swing.JButton;

6.import java.awt.event.ActionEvent;

7.import java.awt.event.ActionListener;

8.import java.awt.GridLayout;

9.public class TaskEditorPanel extends JPanel implements ActionListener, TaskChangeObserver{

10.private JPanel controlPanel, editPanel;

11.private JButton add, update, exit;

12.private JTextField taskName, taskNotes, taskTime;

13.private TaskChangeObservable notifier;

14.private Task editTask;

15.

16.public TaskEditorPanel(TaskChangeObservable newNotifier){

17.notifier = newNotifier;

18.createGui();

19.}

20.public void createGui(){

21.setLayout(new BorderLayout());

22.editPanel = new JPanel();

23.editPanel.setLayout(new GridLayout(3, 2));

24.taskName = new JTextField(20);

25.taskNotes = new JTextField(20);

26.taskTime = new JTextField(20);

27.editPanel.add(new JLabel("Task Name"));

28.editPanel.add(taskName);

29.editPanel.add(new JLabel("Task Notes"));

30.editPanel.add(taskNotes);

31.editPanel.add(new JLabel("Time Required"));

32.editPanel.add(taskTime);

33.

34.controlPanel = new JPanel();

35.add = new JButton("Add Task");

36.update = new JButton("Update Task");

37.exit = new JButton("Exit");

38.controlPanel.add(add);

39.controlPanel.add(update);

40.controlPanel.add(exit);

41.add.addActionListener(this);

42.update.addActionListener(this);

267

43.exit.addActionListener(this);

44.add(controlPanel, BorderLayout.SOUTH);

45.add(editPanel, BorderLayout.CENTER);

46.}

47.public void setTaskChangeObservable(TaskChangeObservable newNotifier){

48.notifier = newNotifier;

49.}

50.public void actionPerformed(ActionEvent event){

51.Object source = event.getSource();

52.if (source == add){

53.

double timeRequired = 0.0;

54.

try{

55.

timeRequired = Double.parseDouble(taskTime.getText());

56.

}

57.

catch (NumberFormatException exc){}

58.notifier.addTask(new Task(taskName.getText(), taskNotes.getText(), timeRequired));

59.}

60.else if (source == update){

61.

editTask.setName(taskName.getText());

62.

editTask.setNotes(taskNotes.getText());

63.

try{

64.

editTask.setTimeRequired(Double.parseDouble(taskTime.getText()));

65.

}

66.

catch (NumberFormatException exc){}

67.

notifier.updateTask(editTask);

68.}

69.else if (source == exit){

70.

System.exit(0);

71.

}

72.

 

73.}

74.public void taskAdded(Task task){ }

75.public void taskChanged(Task task){ }

76.public void taskSelected(Task task){

77.editTask = task;

78.taskName.setText(task.getName());

79.taskNotes.setText(task.getNotes());

80.taskTime.setText("" + task.getTimeRequired());

81.}

82.}

Example A.93 TaskHistoryPanel.java

1.import java.awt.BorderLayout;

2.import javax.swing.JPanel;

3.import javax.swing.JScrollPane;

4.import javax.swing.JTextArea;

5.public class TaskHistoryPanel extends JPanel implements TaskChangeObserver{

6.private JTextArea displayRegion;

7.

8.public TaskHistoryPanel(){

9.createGui();

10.}

11.public void createGui(){

12.setLayout(new BorderLayout());

13.displayRegion = new JTextArea(10, 40);

14.displayRegion.setEditable(false);

15.add(new JScrollPane(displayRegion));

16.}

17.public void taskAdded(Task task){

18.displayRegion.append("Created task " + task + "\n");

19.}

20.public void taskChanged(Task task){

21.displayRegion.append("Updated task " + task + "\n");

22.}

23.public void taskSelected(Task task){

24.displayRegion.append("Selected task " + task + "\n");

25.}

26.}

Example A.94 TaskSelectorPanel.java

1.import java.awt.event.ActionEvent;

2.import java.awt.event.ActionListener;

3.import javax.swing.JPanel;

4.import javax.swing.JComboBox;

5.public class TaskSelectorPanel extends JPanel implements ActionListener,

TaskChangeObserver{

6. private JComboBox selector = new JComboBox();

268

7.private TaskChangeObservable notifier;

8.public TaskSelectorPanel(TaskChangeObservable newNotifier){

9.notifier = newNotifier;

10.createGui();

11.}

12.public void createGui(){

13.selector = new JComboBox();

14.selector.addActionListener(this);

15.add(selector);

16.}

17.public void actionPerformed(ActionEvent evt){

18.notifier.selectTask((Task)selector.getSelectedItem());

19.}

20.public void setTaskChangeObservable(TaskChangeObservable newNotifier){

21.notifier = newNotifier;

22.}

23.

24.public void taskAdded(Task task){

25.selector.addItem(task);

26.}

27.public void taskChanged(Task task){ }

28.public void taskSelected(Task task){ }

29.}

A feature of the Observer pattern is that the Observable uses a standard interface for its Observers —in this case, TaskChangeObserver. This means that the Observer pattern is more generic than the Mediator pattern, but also that the observers may receive some unwanted message traffic. For instance, the TaskEditorPanel takes no action when its taskAdded and taskChanged methods are called.

The Task class represents the business object in the GUI, which in this demonstration is a simple job.

Example A.95 Task.java

1.public class Task{

2.private String name = "";

3.private String notes = "";

4.private double timeRequired;

6.public Task(){ }

7.public Task(String newName, String newNotes, double newTimeRequired){

8.name = newName;

9.notes = newNotes;

10.timeRequired = newTimeRequired;

11.}

12.

13.public String getName(){ return name; }

14.public String getNotes(){ return notes; }

15.public double getTimeRequired(){ return timeRequired; }

16.public void setName(String newName){ name = newName; }

17.public void setTimeRequired(double newTimeRequired){ timeRequired = newTimeRequired; }

18.public void setNotes(String newNotes){ notes = newNotes; }

19.public String toString(){ return name + " " + notes; }

20.}

RunPattern creates the GUI for this example, creating the observable and its observers in the process.

Example A.96 RunPattern.java

1.public class RunPattern{

2.public static void main(String [] arguments){

3.System.out.println("Example for the Observer pattern");

4.System.out.println("This demonstration uses a central observable");

5.System.out.println(" object to send change notifications to several");

6.System.out.println(" JPanels in a GUI. Each JPanel is an Observer,");

7.System.out.println(" receiving notifcations when there has been some");

8.System.out.println(" change in the shared Task that is being edited.");

9.System.out.println();

10.

11.System.out.println("Creating the ObserverGui");

12.ObserverGui application = new ObserverGui();

13.application.createGui();

14.}

15.}

269