Sunteți pe pagina 1din 11

Paradigme de Programare Laboratorul 12

Laboratorul 12
12.1. abloane comportamentale
abloanele comportamentale se ocup cu algoritmi i cu atribuirea responsabilitilor ntre obiecte. Pe lng abloanele de obiecte sau de clase, acestea descriu i abloanele de comunicare ntre clase/obiecte. Aceste abloane ajut la concentrarea mai mult asupra modului n care sunt interconectate obiectele i mai puin asupra fluxului complex de control dificil de urmrit la execuie. abloanele comportamentale de clas folosesc motenirea pentru a distribui comportarea ntre clase. Acest grup cuprinde 2 abloane: Template Method i Intepreter. Template Method se refer la o metod ce reprezint o definiie abstract a unui algoritm. Algoritmul este definit pas cu pas, fiecare pas apelnd o operaie abstract sau o operaie primitiv. O subclas ce extinde clasa n cauz completeaz algoritmul, oferind implementri concrete metodelor abstracte. Un Interpreter este o gramatic sub form de ierarhie de clase care implementeaz un interpretor ca o operaie pe instanele acestor clase. abloanele comportamentale de obiect folosesc compunerea obiectelor. Unele dintre aceste abloane descriu felul n care coopereaz un grup de obiecte egale pentru a efectua o operaie ce nu ar fi putut fi efectuat de un singur obiect. Un aspect important este modul n care aceste obiecte egale tiu unele de celelalte. ablonul Observer de exemplu definete o dependen ntre obiecte, un exemplu clasic fiind sistemul MVC (Model View Controller), unde toate vizualizrile unui model sunt ntiinate oricnd modelul i modific starea. Alte abloane ncapsuleaz comportarea ntr-un obiect i deleag cererile ctre acest obiect. 12.1.1. Observer 1) Definiie Se definete o dependen unu la muli ntre obiecte, astfel nct dac un obiect i modific starea, toate obiectele dependente de acesta vor fi notificate. ablonul mai este cunoscut i sub numele de Publish Subscribe sau Dependenti. 2) Aplicabilitate i beneficii Acest ablon permite variaia independent a observatorilor i a obiectelor observate. Se pot reutiliza unele dintre ele, fr a le refolosi pe celelalte. Se pot de asemenea aduga observatori fr a modifica obiectele observate sau ceilali observatori. Cnd se aplic - cnd abstractizarea are dou aspecte, unul depinznd de cellalt. ncapsularea n obiecte separate permite variaia lor n mod independent. - cnd modificarea unui obiect necesit i modificarea altor obiecte, fr a ti care este numrul acestora. - cnd un obiect trebuie s notifice alte obiecte fr s necesite cunoaterea identitii acestora (nu dorim legarea strns ntre acestea) Avantaje

Paradigme de Programare Laboratorul 12 - cuplare abstract ntre subiect i observatori: subiectul are o list de observatori care se conformeaz unei interfee simple, cuplarea fiind redus la minim - comunicare pe scar larg: subiectul nu este interesat de destinatarii unei notifcri, el trimite mesajul tuturor celor abonai la momentul respectiv. Acest lucru permite adugarea i eliminarea de observatori n orice moment necesar. 3) Structura

4) Participani Subject Reine i poate fi observat de mai muli observatori; furnizeaz o interfa pentru ataarea i detaarea acestora Observer Definete interfaa de actualizare ce trebuie implementat de ctre obiectele ce doresc notificri de la Subject ConcreteSubject Reine informaiile ce reprezint interes pentru obiectele observator. Cnd i se modific starea trimite notifcri ctre observatori ConcreteObsever Pastreaz o referin ctre un obiect Subject, reine o stare consecvent cu cea a subiectului i implementeaz Observer pentru a-i putea menine aceast stare n concordan.

Paradigme de Programare Laboratorul 12

12.2. Exemple
1) Exemplu folosire Obsever i Observable API-ul Java ofer dou interfee pentru a uura implementarea acestui ablon: Obsever i Observable. Exemplul urmtor arat cum pot fi folosite aceste interfee.
// MessageBoard.java package test; import java.util.Observable; public class MessageBoard extends Observable { private String message; public String getMessage() { return message; } public void changeMessage(String message) { this.message = message; setChanged(); notifyObservers(message); } public static void main(String[] args) { MessageBoard board = new MessageBoard(); Student bob = new Student(); Student joe = new Student(); board.addObserver(bob); board.addObserver(joe); board.changeMessage("More Homework!"); } } // Student.java package test; import java.util.Observable; import java.util.Observer; class Student implements Observer { public void update(Observable o, Object arg) { System.out.println("Message board changed: " + arg); } }

2) Folosire n GUI ablonul Observer este des folosit n aplicaiile cu interfa utilizator grafic GUI. De exemplu atunci cnd date statistice sufer modificri, mai multe obiecte grafice vor trebui actualizate conform noilor valori: liste, tabele, diagrame .a. Clasa subject n acest exemplu este o fereastr n care se introduce un text, iar clasa observer este o alt fereastr ce afieaz textele introduse n prima fereastr.
// InputForm.java

Paradigme de Programare Laboratorul 12


package test; import import import import import import import import import java.awt.event.ActionEvent; java.awt.event.ActionListener; java.awt.event.WindowAdapter; java.awt.event.WindowEvent; java.util.Observable; javax.swing.JFrame; javax.swing.JLabel; javax.swing.JPanel; javax.swing.JTextField;

@SuppressWarnings("serial") class InputForm extends JFrame { public InformDisplay inform = new InformDisplay(); // ... JTextField input = new JTextField(10); public InputForm() { JPanel panel = new JPanel(); input.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { inform.notifyObservers(); } }); panel.add(new JLabel("Enter: ")); panel.add(input); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); getContentPane().add(panel); setTitle("Observable form"); setSize(200, 100); setVisible(true); } public Observable getInputInfo() { return inform; } public String getText() { return input.getText(); } private class InformDisplay extends Observable { public void notifyObservers() { setChanged(); super.notifyObservers(); } } // ... } // DisplayForm.java package test; import javax.swing.*;

Paradigme de Programare Laboratorul 12


import java.awt.event.*; import java.util.*; @SuppressWarnings("serial") class DisplayForm extends JFrame { InputForm inputForm; Observable obsInput; JTextField display; // ... public DisplayForm() { addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); inputForm = new InputForm(); obsInput = inputForm.getInputInfo(); obsInput.addObserver(new InputFormObserver()); display = new JTextField(10); add(display); setTitle("Observer form"); setSize(200, 100); setLocation(200, 100); setVisible(true); } private class InputFormObserver implements Observer { public void update(Observable ob, Object o) { doSomeUpdate(); } } public void doSomeUpdate() { display.setText(inputForm.getText()); JOptionPane.showMessageDialog(DisplayForm.this, "This form has been updated"); } public static void main(String args[]) { new DisplayForm(); } }

12.3. Aplicaie
Aplicaia urmtoare ofer un sistem minimal de organizare a task-urilor din cadrul unei echipe de programare. Diagrama UML este urmtoarea:

Paradigme de Programare Laboratorul 12

Paradigme de Programare Laboratorul 12

Un task n sine este reprezentat de clasa Task, care conine 3 parametri i ofer gettere i settere pentru acetia conform diagramei. Ofer de asemenea o implementare a metodei toString:
public String toString() { return name + " " + notes; }

Operaiile asupra listei de task-uri curente la un moment dat vor genera nite evenimente ce vor fi ascultate de ctre observatori. Implementarea actorului Subject este dat de clasa TaskChangeObservable. Aceasta reine o list editabil de observatori i face dispatch-ul evenimentelor ctre aceti observeri.
private ArrayList<TaskChangeObserver> ArrayList<TaskChangeObserver>(); observers = new

Partea grafic a aplicaiei este format din 3 zone, fiecare necesitnd actualizare atunci cnd lista de task-uri sufer modificri. Pentru o mai uoar implementare se realizeaz o ierarhie de clase ce are la baz clasa TaskPanel:
public abstract class TaskPanel extends JPanel implements ActionListener { public void actionPerformed(ActionEvent e) { } public abstract TaskChangeObserver getObsever(); }

Toate cele 3 clase Panel care vor extinde TaskPanel vor implementa ntr-un fel sau altul interfaa Observer:
interface TaskChangeObserver { public void taskAdded(Task task); public void taskChanged(Task task); public void taskSelected(Task task); }

Cum nu toate dintre ele au nevoie de toate metodele din aceast interfa, vom face i un wrapper ajuttor n acest sens (Adapter pattern):
class TaskChangeObserverAdapter implements TaskChangeObserver { public void taskAdded(Task task) { } public void taskChanged(Task task) { } public void taskSelected(Task task) { } }

Dac nu toate panel-urile vor implementa interfaa TaskChangeObserver i nici nu pot extinde clasa Adapter, atunci toate trebuie s ofere un mod uniform de a oferi un obiect de tip Observer, lucru 7

Paradigme de Programare Laboratorul 12 realizat prin metoda getObserver din TaskPanel. Clasele care nu implementeaz interfaa vor folosi compunerea: o instan privat realizat printr-o clas intern. TaskEditorPanel este zona care ofer posibilitatea de a crea un task sau de a modifica parametrii unui task deja existent. Acest panel rspunde la evenimentul de selectare a unui nou task i genereaz evenimentele de creare i modificare de task.
package test; import import import import import import import java.awt.BorderLayout; java.awt.GridLayout; java.awt.event.ActionEvent; javax.swing.JButton; javax.swing.JLabel; javax.swing.JPanel; javax.swing.JTextField;

@SuppressWarnings("serial") class TaskEditorPanel extends TaskPanel { private TaskChangeObserver taskObserver; private JPanel controlPanel; private JPanel editPanel; private JButton add; private JButton update; private JButton exit; private JTextField taskName; private JTextField taskNotes; private JTextField taskTime; private TaskChangeObservable notifier; private Task editTask; public TaskEditorPanel(TaskChangeObservable newNotifier) { notifier = newNotifier; taskObserver = new TaskChangeObserverAdapter() { public void taskSelected(Task task) { editTask = task; taskName.setText(task.getName()); taskNotes.setText(task.getNotes()); taskTime.setText("" + task.getTimeRequired()); } }; createGui(); } public void createGui() { setLayout(new BorderLayout()); editPanel = new JPanel(); editPanel.setLayout(new GridLayout(3, 2)); taskName = new JTextField(20); taskNotes = new JTextField(20); taskTime = new JTextField(20); editPanel.add(new JLabel("Task Name")); editPanel.add(taskName); editPanel.add(new JLabel("Task Notes")); editPanel.add(taskNotes);

Paradigme de Programare Laboratorul 12


editPanel.add(new JLabel("Time Required")); editPanel.add(taskTime); controlPanel = new JPanel(); add = new JButton("Add Task"); update = new JButton("Update Task"); exit = new JButton("Exit"); controlPanel.add(add); controlPanel.add(update); controlPanel.add(exit); add.addActionListener(this); update.addActionListener(this); exit.addActionListener(this); add(controlPanel, BorderLayout.SOUTH); add(editPanel, BorderLayout.CENTER); } public void actionPerformed(ActionEvent event) { Object source = event.getSource(); if (source == add) { double timeRequired = 0.0; try { timeRequired = Double.parseDouble(taskTime.getText()); } catch (NumberFormatException exc) { } notifier.addTask(new Task(taskName.getText(), taskNotes.getText(), timeRequired)); } else if (source == update) { editTask.setName(taskName.getText()); editTask.setNotes(taskNotes.getText()); try { editTask .setTimeRequired(Double.parseDouble(tas kTime.getText())); } catch (NumberFormatException exc) { } notifier.updateTask(editTask); } else if (source == exit) { System.exit(0); } } @Override public TaskChangeObserver getObsever() { return taskObserver; } }

TaskSelectorPane reprezint zona unde se poate alege un task din lista de task-uri deja create. Aceast zon rspunde la evenimentul de creare de nou task, care este introdus n list, i genereaz evenimentul de selecie a unui nou task.
package test; import java.awt.event.ActionEvent; import javax.swing.JComboBox; @SuppressWarnings("serial")

Paradigme de Programare Laboratorul 12


class TaskSelectorPanel extends TaskPanel { private TaskChangeObserver taskObserver; private JComboBox selector = new JComboBox(); private TaskChangeObservable notifier; public TaskSelectorPanel(TaskChangeObservable newNotifier) { notifier = newNotifier; taskObserver = new TaskChangeObserverAdapter() { public void taskAdded(Task task) { selector.addItem(task); } }; createGui(); } public void createGui() { selector = new JComboBox(); selector.addActionListener(this); add(selector); } public void actionPerformed(ActionEvent evt) { notifier.selectTask((Task) selector.getSelectedItem()); } @Override public TaskChangeObserver getObsever() { return taskObserver; } }

TaskHistoryPanel este zona de mesaje n care se rein toate operaiile efectuate. Se ascult toate evenimentele generate de Subject i nu se genereaz nici unul.
package test; import java.awt.BorderLayout; import javax.swing.JScrollPane; import javax.swing.JTextArea; @SuppressWarnings("serial") class TaskHistoryPanel extends TaskPanel implements TaskChangeObserver { private JTextArea displayRegion; public TaskHistoryPanel() { createGui(); } public void createGui() { setLayout(new BorderLayout()); displayRegion = new JTextArea(10, 40); displayRegion.setEditable(false); add(new JScrollPane(displayRegion)); } public void taskAdded(Task task) { displayRegion.append("Created task " + task + "\n");

10

Paradigme de Programare Laboratorul 12


} public void taskChanged(Task task) { displayRegion.append("Updated task " + task + "\n"); } public void taskSelected(Task task) { displayRegion.append("Selected task " + task + "\n"); } @Override public TaskChangeObserver getObsever() { return this; } }

Partea de interfa grafic, unde se instaniaz aceste panel-uri, ar putea cuprinde urmtoarele:
TaskPanel select = new TaskSelectorPanel(observable); TaskPanel history = new TaskHistoryPanel(); TaskPanel edit = new TaskEditorPanel(observable); observable.addTaskChangeObserver(select.getObsever()); observable.addTaskChangeObserver(history.getObsever()); observable.addTaskChangeObserver(edit.getObsever()); observable.addTask(new Task());

12.4. Teme
12.4.1. Tema 1 Extindei aplicaia de la seciunea 12.2 astfel nct mai multe ferestre observer s asculte mesajele introduse in fereastra subiect. Numrul acestor ferestre trebuie s fie variabil i s poat fi controlat n timpul rulrii. De exemplu un buton n fereastra display permite instanierea unui nou observer, iar inchiderea unei ferestre observer nu mai duce la nchiderea ntregii aplciaii. 12.4.2. Tema 2 Construii clasele i interfeele conform diagramei i explicaiilor de la seciunea 12.3 i realizai fereastra grafic care s cuprind cele 3 panel-uri. Extindei aplicaia astfel nct s se poate terge task-urile selectate.

11

S-ar putea să vă placă și