printer - Software Engineering

Werbung
Einführung in Software Engineering
Übung 9:
Design Patterns
Richard Bubel & Martin Hentschel
31. Januar 2013
130131 | TUD | M. Hentschel | 1
Aufgabe 9.1 (7 Punkte)
I
Ziel: Entwurfsmuster verstehen und anwenden
I
Beschreibung: Anwendung Registrierkasse (Cash Register) erfasst
Positionen eines Kassenbelegs und berechnet den Gesamtbetrag
130131 | TUD | M. Hentschel | 2
Aufgabe 9.1a (2 Punkte)
I
Ziel: Entwurfsmuster „Strategy“ anwenden
I
Beschreibung: Angezeigte Positionen anhand Beschreibung filterbar
I
Aufgabe: Anforderung mit Entwurfmuster „Strategy“ implementieren
130131 | TUD | M. Hentschel | 3
Aufgabe 9.1a (Lösungsvorschlag)
Struktur
VisualbParadigmbforbUMLbStandardbEditionwTUbDarmstadtv
CashRegisterFrame
1updateShownReceiptwvb:bvoid
<<create>>
ReceiptPrinter
filter
1ReceiptPrinterwfilterb:bIReceiptPositionFilterv
1printReceiptwreceiptb:bReceiptvb:bString
DescriptionReceiptPositionFilter
-filterb:bString
1DescriptionReceiptPositionFilterwfilterb:bStringv
1acceptwpositionb:bReceiptPositionvb:bboolean
130131 | TUD | M. Hentschel | 4
<<create>>
1
<<Interface>>
IReceiptPositionFilter
1acceptwpositionb:bReceiptPositionvb:bboolean
AllReceiptFilter
1AllReceiptFilterwv
1acceptwpositionb:bReceiptPositionvb:bboolean
Aufgabe 9.1a (Lösungsvorschlag)
Quellcode
public interface IReceiptPositionFilter {
public boolean accept(ReceiptPosition position);
}
130131 | TUD | M. Hentschel | 5
Aufgabe 9.1a (Lösungsvorschlag)
Quellcode
public class AllReceiptFilter implements IReceiptPositionFilter {
@Override
public boolean accept(ReceiptPosition position) {
return true;
}
}
130131 | TUD | M. Hentschel | 6
Aufgabe 9.1a (Lösungsvorschlag)
Quellcode
public class DescriptionReceiptPositionFilter
implements IReceiptPositionFilter {
private String filter;
public DescriptionReceiptPositionFilter(String filter) {
this.filter = filter;
}
@Override public boolean accept(ReceiptPosition position) {
if (position != null) {
String description = position.getDescription();
return description != null && description.contains(filter);
}
else {
return false;
}
}
}
130131 | TUD | M. Hentschel | 7
Aufgabe 9.1a (Lösungsvorschlag)
Quellcode
public class ReceiptPrinter {
private IReceiptPositionFilter filter;
public ReceiptPrinter(IReceiptPositionFilter filter) {
this.filter = filter;
}
}
public String printReceipt(Receipt receipt) {
// ...
for (ReceiptPosition position : positions) {
if (filter == null || filter.accept(position)) {
// ...
}
}
// ...
}
130131 | TUD | M. Hentschel | 8
Aufgabe 9.1a (Lösungsvorschlag)
Quellcode
public class CashRegisterFrame extends JFrame {
protected void updateShownReceipt() {
// Get filter text
String filterText = filterField.getText();
// Create new text to show in receipt area
IReceiptPositionFilter filter =
filterText != null && !filterText.isEmpty() ?
new DescriptionReceiptPositionFilter(filterText) :
new AllReceiptFilter();
ReceiptPrinter printer = new ReceiptPrinter(filter);
String receiptText = printer.printReceipt(receipt);
// Update shown text
receiptArea.setText(receiptText);
}
}
130131 | TUD | M. Hentschel | 9
Aufgabe 9.1b (2,5 Punkte)
I
Ziel: Entwurfsmuster „Observer“ anwenden
I
Beschreibung: Kassenbeleg in zwei Fenstern editierbar
I
Aufgabe: Anforderung mit Entwurfmuster „Observer“ implementieren
130131 | TUD | M. Hentschel | 10
Aufgabe 9.1b (Lösungsvorschlag)
Struktur (Observable)
Visual:Paradigm:for:UML:Standard:EditionbTU:DarmstadtO
CashRegisterFrame
receiptObserver
jCashRegisterFramebtitle:::String$:receipt:::ReceiptO
jdisposebO:::void
pupdateShownReceiptbO:::void
0
CashRegisterFramev0
jupdatebo:::Observable$:arg:::ObjectO:::void
<<Interface>>
Observer
ReceiptPosition
><<y
receipt
jupdatebo:::Observable$:arg:::ObjectO:::void
><<y
positions
0
Receipt
jaddPositionbposition:::ReceiptPositionO:::void
130131 | TUD | M. Hentschel | 11
obs
Observable
1changed:::boolean
jaddObserverbo:::ObserverO:::void
jdeleteObserverbo:::ObserverO:::void
psetChangedbO:::void
jnotifyObserversbarg:::ObjectO:::void
Aufgabe 9.1b (Lösungsvorschlag)
Quellcode (Observable)
import java.util.LinkedList;
import java.util.List;
import java.util.Observable;
public class Receipt extends Observable {
private List<ReceiptPosition> positions =
new LinkedList<ReceiptPosition>();
public void addPosition(ReceiptPosition position) {
if (positions.add(position)) {
setChanged();
notifyObservers(position); // Resets changed flag
}
}
}
130131 | TUD | M. Hentschel | 12
Aufgabe 9.1b (Lösungsvorschlag)
Quellcode (Observable)
import java.util.Observable;
public class CashRegisterFrame extends JFrame {
private Observer receiptObserver = new Observer() {
@Override public void update(Observable o, Object arg) {
updateShownReceipt();
}
};
public CashRegisterFrame(String title, Receipt receipt) {
/* ... */ this.receipt.addObserver(receiptObserver); /* ... */
}
@Override public void dispose() {
this.receipt.deleteObserver(receiptObserver); super.dispose();
}
protected void updateShownReceipt() { /* ... */ }
}
130131 | TUD | M. Hentschel | 13
Aufgabe 9.1b (Lösungsvorschlag)
Struktur (Listener)
Visual:Paradigm:for:UML:Standard:EditionATU:Darmstadt<
CashRegisterFrame
receiptListener 0
-CashRegisterFrameAtitle:::StringO:receipt:::Receipt<
-disposeA<
pupdateShownReceiptA<:::void
0
receipt
Receipt
-addPositionAposition:::ReceiptPosition<:::void
-addReceiptListenerAlistener:::IReceiptListener<:::void
-removeReceiptListenerAlistener:::IReceiptListener<:::voidA<
-fireReceiptPositionAddedAe:::ReceiptEvent<:::void
1jj>
positions
ReceiptPosition
CashRegisterFrame#0
-receiptPositionAddedAe:::ReceiptEvent<:::void
listeners
1jj0
<<Interface>>
IReceiptListener
-receiptPositionAddedAe:::ReceiptEvent<:::void
<<use>>
<<create>>
ReceiptEvent
baddedPosition:::ReceiptPosition
-ReceiptEventAsource:::ReceiptO:addedPosition:::ReceiptPosition<
-getSourceA<:::Receipt
-getAddedPositionA<:::ReceiptPosition
130131 | TUD | M. Hentschel | 14
<<Interface>>
EventListener
EventObject
Aufgabe 9.1b (Lösungsvorschlag)
Quellcode (Listener)
import java.util.EventListener;
public interface IReceiptListener extends EventListener {
public void receiptPositionAdded(ReceiptEvent e);
}
130131 | TUD | M. Hentschel | 15
Aufgabe 9.1b (Lösungsvorschlag)
Quellcode (Listener)
import java.util.EventObject;
public class ReceiptEvent extends EventObject {
private ReceiptPosition addedPosition;
public ReceiptEvent(Receipt source,
ReceiptPosition addedPosition) {
super(source);
this.addedPosition = addedPosition;
}
@Override public Receipt getSource() {
return (Receipt)super.getSource();
}
public ReceiptPosition getAddedPosition() {
return addedPosition;
}
}
130131 | TUD | M. Hentschel | 16
Aufgabe 9.1b (Lösungsvorschlag)
Quellcode (Listener)
import javax.swing.event.EventListenerList;
public class Receipt {
private EventListenerList listeners = new EventListenerList();
}
public void addReceiptListener(IReceiptListener listener) {
if (listener != null) {
listeners.add(IReceiptListener.class, listener);
}
}
public void removeReceiptListener(IReceiptListener listener) {
if (listener != null) {
listeners.remove(IReceiptListener.class, listener);
}
}
130131 | TUD | M. Hentschel | 17
Aufgabe 9.1b (Lösungsvorschlag)
Quellcode (Listener)
import javax.swing.event.EventListenerList;
public class Receipt {
private EventListenerList listeners = new EventListenerList();
}
protected void fireReceiptPositionAdded(ReceiptEvent e) {
IReceiptListener[] toInform = listeners.getListeners(
IReceiptListener.class);
for (IReceiptListener l : toInform) {
l.receiptPositionAdded(e);
}
}
130131 | TUD | M. Hentschel | 18
Aufgabe 9.1b (Lösungsvorschlag)
Quellcode (Listener)
import java.util.LinkedList;
import java.util.List;
public class Receipt {
private List<ReceiptPosition> positions =
new LinkedList<ReceiptPosition>();
public void addPosition(ReceiptPosition position) {
if (positions.add(position)) {
fireReceiptPositionAdded(new ReceiptEvent(this, position));
}
}
// ...
}
130131 | TUD | M. Hentschel | 19
Aufgabe 9.1b (Lösungsvorschlag)
Quellcode (Listener)
public class CashRegisterFrame extends JFrame {
private IReceiptListener rcptListener = new IReceiptListener() {
@Override
public void receiptPositionAdded(ReceiptEvent e) {
updateShownReceipt();
}
};
public CashRegisterFrame(String title, Receipt receipt) {
/* ... */ receipt.addReceiptListener(rcptListener); /* ... */
}
@Override public void dispose() {
receipt.removeReceiptListener(rcptListener);
super.dispose();
}
protected void updateShownReceipt() { /* ... */ }
}
130131 | TUD | M. Hentschel | 20
Aufgabe 9.1b (Lösungsvorschlag)
Struktur (Bean)
Visual:Paradigm:for:UML:Standard:Edition_TU:DarmstadtI
CashRegisterFrame
receiptListener
yCashRegisterFrame_title:::Stringx:receipt:::ReceiptI
ydispose_I:::void
pupdateShownReceipt_I:::void
<
CashRegisterFramev<
ypropertyChange_evt:::PropertyChangeEventI:::void
<<Interface>>
PropertyChangeListener
receipt
ypropertyChange_evt:::PropertyChangeEventI:::void
<
Receipt
1jjN
yPROP_POSITIONS:::String
yaddPosition_position:::ReceiptPositionI:::void
yaddPropertyChangeListener_propertyName:::Stringx:listener:::PropertyChangeListenerI:::void
yremovePropertyChangeListener_propertyName:::Stringx:listener:::PropertyChangeListenerI:::void
ReceiptPosition
1jjN
ReceiptPosition
130131 | TUD | M. Hentschel | 21
<
pcs
<
source
<<use>>
listeners
PropertyChangeEvent
<<create>>
PropertyChangeSupport
yaddPropertyChangeListener_propertyName:::Stringx:listener:::PropertyChangeListenerI:::void
yremovePropertyChangeListener_propertyName:::Stringx:listener:::PropertyChangeListenerI:::void
yfireIndexedPropertyChange_propertyName:::Stringx:index:::intx:oldValue:::Objectx:newValue:::ObjectI:::void
yfirePropertyChange_propertyName:::Stringx:oldValue:::Objectx:newValue:::ObjectI:::void
Aufgabe 9.1b (Lösungsvorschlag)
Quellcode (Bean)
import java.beans.PropertyChangeSupport;
public class Receipt {
public static final String PROP_POSITIONS = "positions";
private PropertyChangeSupport pcs =
new PropertyChangeSupport(this);
private List<ReceiptPosition> positions =
new LinkedList<ReceiptPosition>();
}
public void addPosition(ReceiptPosition position) {
int index = positions.size();
if (positions.add(position)) {
pcs.fireIndexedPropertyChange(PROP_POSITIONS, index,
null, position);
}
}
130131 | TUD | M. Hentschel | 22
Aufgabe 9.1b (Lösungsvorschlag)
Quellcode (Bean)
import java.beans.PropertyChangeListener;
public class Receipt {
public void addPropertyChangeListener(String propertyName,
PropertyChangeListener listener) {
if (listener != null) {
pcs.addPropertyChangeListener(propertyName, listener);
}
}
}
public void removePropertyChangeListener(String propertyName,
PropertyChangeListener listener) {
if (listener != null) {
pcs.removePropertyChangeListener(propertyName, listener);
}
}
130131 | TUD | M. Hentschel | 23
Aufgabe 9.1b (Lösungsvorschlag)
Quellcode (Bean)
import java.beans.PropertyChangeListener;
public class Receipt {
public void addPropertyChangeListener(String propertyName,
PropertyChangeListener listener) {
if (listener != null) {
pcs.addPropertyChangeListener(propertyName, listener);
}
}
}
public void removePropertyChangeListener(String propertyName,
PropertyChangeListener listener) {
if (listener != null) {
pcs.removePropertyChangeListener(propertyName, listener);
}
}
130131 | TUD | M. Hentschel | 24
Aufgabe 9.1b (Lösungsvorschlag)
Quellcode (Bean)
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
public class CashRegisterFrame extends JFrame {
private PropertyChangeListener receiptListener =
new PropertyChangeListener() {
@Override public void propertyChange(PropertyChangeEvent evt){
updateShownReceipt();
}
};
public CashRegisterFrame(String title, Receipt receipt) {
/* ... */
receipt.addPropertyChangeListener(Receipt.PROP_POSITIONS,
receiptListener); /* ... */
}
}
130131 | TUD | M. Hentschel | 25
Aufgabe 9.1b (Lösungsvorschlag)
Quellcode (Bean)
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
public class CashRegisterFrame extends JFrame {
@Override
public void dispose() {
receipt.removePropertyChangeListener(Receipt.PROP_POSITIONS,
receiptListener);
super.dispose();
}
protected void updateShownReceipt() {
/* ... */
}
}
130131 | TUD | M. Hentschel | 26
Aufgabe 9.2 (2 Punkte)
I
Ziel: Angewendete Entwurfsmuster erkennen
I
Beschreibung: Ausschnitt der Java 6 API Spezifikation einer Klasse gegeben
I
Aufgabe:
I
I
Entwurfsmuster des Ausschnitts nennen
Elemente der Java API den Bestandteilen des Entwurfmusters zuordnen
130131 | TUD | M. Hentschel | 27
Aufgabe 9.2a (Lösungsvorschlag)
Class javax.swing.AbstractListModel
130131 | TUD | M. Hentschel | 28
Aufgabe 9.2a (Lösungsvorschlag)
Class javax.swing.AbstractListModel
I
Observer Design Pattern
Subjekt
Beobachter verwalten
Beobachter informieren
Konkretes Subjekt
Abstrakter Beobachter
Konkrete Beobachter
130131 | TUD | M. Hentschel | 29
AbstractListModel
addListDataListener(ListDataListener),
getListDataListeners(),
removeListDataListener(ListDataListener)
fireContentsChanged(... ),
fireIntervalAdded(... ),
fireIntervalRemoved(... )
BasicDirectoryModel, DefaultComboBoxModel, ...
ListDataListener
JComboBox
Aufgabe 9.2b (Lösungsvorschlag)
Class javax.swing.JFileChooser extends javax.swing.JComponent
130131 | TUD | M. Hentschel | 30
Aufgabe 9.2b (Lösungsvorschlag)
Class javax.swing.JFileChooser extends javax.swing.JComponent
I
Strategy Design Pattern
Kontext
Abstrakte Strategie
Strategie-Methode
Konkrete Strategien
130131 | TUD | M. Hentschel | 31
JFileChooser
FileFilter
accept(File)
BasicFileChooserUI.AcceptAllFileFilter,
FileNameExtensionFilter
Herunterladen