No Slide Title
Download
Report
Transcript No Slide Title
CENG 217 Object Oriented Design
Lecture 5
Doç. Dr. Halûk Gümüşkaya
[email protected] / [email protected]
http://www.gumuskaya.com
Computing Engineering Department
Fatih University
Tuesday, July 21, 2015
1
Patterns and
GUI Programming
2
Lecture Outline
1. The ITERATOR as a Pattern
2.
The Pattern Concept and Introduction to GoF Design
Patterns
3.
The OBSERVER Pattern
4.
Layout Managers and the STRATEGY Pattern
5.
Components, Containers, and the COMPOSITE Pattern
6.
Scroll Bars and the DECORATOR Pattern
7.
How to Recognize Patterns
8.
Putting Patterns to Work
3
List Iterators
LinkedList<String> list = . . .;
ListIterator<String> iterator = list.listIterator();
while (iterator.hasNext())
{
String current = iterator.next();
. . .
}
Why iterators?
Classical List Data Structure
Traverse links directly
Link currentLink = list.head;
while (currentLink != null)
{
Object current = currentLink.data;
currentLink = currentLink.next;
}
Exposes implementation
Error-prone
4
High-Level View of Data Structures
Queue
Array with random access
List
???
5
List with Cursor
for (list.reset(); list.hasNext(); list.next())
{
Object x = list.get();
. . .
}
Disadvantage: Only one cursor per list , debugging!!!
Iterator is superior concept
6
1.
The ITERATOR as a Pattern
2. The Pattern Concept and Introduction to
GoF Design Patterns
3.
The OBSERVER Pattern
4.
Layout Managers and the STRATEGY Pattern
5.
Components, Containers, and the COMPOSITE Pattern
6.
Scroll Bars and the DECORATOR Pattern
7.
How to Recognize Patterns
8.
Putting Patterns to Work
7
What is a Pattern? History: Architectural Patterns
• Current use comes from the work of the architect Christopher
Alexander.
• Alexander studied ways to improve the process of designing
buildings and urban areas.
• He formulated over 250 patterns for architectural designs.
C. Alexander et al., A Pattern Language: Towns, Buildings,
Construction, Oxford University Press, 1977.
• Patterns can be applied to many different areas of human
endeavor, including software development…
There are patterns of success, and patterns of failure…
8
The Pattern Concept: Context, Problem and Solution
• “Each pattern is a three-part rule, which expresses a relation
between a certain context, a problem and a solution.”
• Hence, the common definition of a pattern:
“A solution to a problem in a context.”
• Each pattern has
• a short name
• a brief description of the context
• a lengthy description of the problem
• a prescription for the solution
9
Short Passages Pattern
Context
"...Long, sterile corridors set the
scene for everything bad
about modern architecture..."
Problem
a lengthy description of the
problem, including
• a depressing picture
• issues of light and furniture
• research about patient
anxiety in hospitals
• research that suggests that
corridors over 50 ft are
considered uncomfortable
10
Short Passages Pattern
Solution
Keep passages short. Make them as much like rooms as possible,
with carpets or wood on the floor, furniture, bookshelves, beautiful
windows. Make them generous in shape and always give them
plenty of light; the best corridors and passages of all are those which
have windows along an entire wall.
11
Why Patterns?
• “Designing object-oriented software is hard and designing
reusable object-oriented software is even harder.” - Erich Gamma
• Experienced designers reuse solutions that have worked in the
past.
• Well-structured object-oriented systems have
recurring patterns of classes and objects.
• Knowledge of the patterns that have worked in the past allows a
designer to be more productive and the resulting designs to
be more flexible and reusable.
12
Benefits of Design Patterns
• Capture expertise and make it accessible to non-experts in a
standard form
• Facilitate communication among developers by providing a
common language
• Make it easier to reuse successful designs and avoid
alternatives that diminish reusability
• Facilitate design modifications
• Improve design documentation
• Improve design understandability
13
Drawbacks of Design Patterns
• Patterns do not lead to direct code reuse
• Patterns are deceptively simple
• Teams may suffer from pattern overload
• Patterns are validated by experience and discussion rather than
by automated testing
• Integrating patterns into a software development process is a
human-intensive activity
14
Software Patterns History
• 1987 - Cunningham and Beck used Alexander’s ideas to develop a
small pattern language for Smalltalk
• 1990 - The Gang of Four (Gamma, Helm, Johnson and Vlissides)
begin work compiling a catalog of design patterns
• 1991 - Bruce Anderson gives first Patterns Workshop at OOPSLA
• 1993 - Kent Beck and Grady Booch sponsor the first meeting of what
is now known as the Hillside Group
• 1994 - First Pattern Languages of Programs (PLoP) conference
• 1995 - The Gang of Four (GoF)
publish the Design Patterns book
15
GoF (Gang of Four) Design Patterns
• Erich Gamma, Richard Helm, Ralph
Johnson, John Vlissides
(Gang of Four – GoF),
Design Patterns: Elements of Reusable
Object-Oriented Software, Addison
Wesley, 1995.
• There are 23 design patterns given in
this book. They are classified into 3
purposes:
Creational,
Structural, and
Behavioral.
16
GoF Classification Of Design Patterns
17
GoF Essential Elements Of Design Patterns
18
GoF Pattern Template
19
GoF Pattern Template (Continued)
20
GoF Pattern Template (Continued)
21
GoF Notation
• The GoF book uses the Object Modeling Technique (OMT) notation
for class and object diagrams:
Notational issues
Attributes come after the Operations
Associations are called acquaintances
Multiplicities are shown as solid circles
Inheritance shown as triangle
Dashed line: Instantiation Association (Class can instantiate
objects of associated class) (In UML it denotes a dependency
UML Note is called Dogear box (connected by dashed line to
class operation): Pseudo-code implementation of operation
22
GoF Notation Example
23
UML Notation for Design Patterns
• We will use UML in design patterns.
24
Creational Patterns (5 patterns)
• Factory Method (OODP Chp10)
– Method in a derived class creates associates
• Abstract Factory
– Factory for building related objects
• Builder
– Factory for building complex objects incrementally
• Prototype
– Factory for cloning new instances from a prototype
• Singleton (OODP Chp10)
– Factory for a singular (sole) instance
25
Structural Patterns (7 patterns)
• Adapter (OODP Chp10)
– Translator adapts a server interface for a client
• Bridge
– Abstraction for binding one of many implementations
• Composite (OODP Chp5)
– Structure for building recursive aggregations
• Decorator (OODP Chp5)
– Decorator extends an object transparently
• Facade
– Facade simplifies the interface for a subsystem
• Flyweight
– Many fine-grained objects shared efficiently
• Proxy (OODP Chp10)
– One object approximates another
26
Behavioral Patterns (11 patterns)
• Chain of Responsibility
– Request delegated to the responsible service provider
• Command (OODP Chp10)
– Request as first-class object
• Interpreter
– Language interpreter for a small grammar
• Iterator (OODP Chp5)
– Aggregate elements are accessed sequentially
• Mediator
– Mediator coordinates interactions between its associates
• Memento
– Snapshot captures and restores object states privately
27
Behavioral Patterns (continued)
• Observer (OODP Chp5)
– Dependents update automatically when a subject changes
• State
– Object whose behavior depends on its state
• Strategy (OODP Chp5)
– Abstraction for selecting one of many algorithms
• Template Method
– Algorithm with some steps supplied by a derived class
• Visitor (OODP Chp10)
– Operations applied to elements of an heterogeneous object
structure
28
Relationships in GoF Patterns
29
An Example: Iterator Pattern
Context
1. An aggregate object contains element objects
2. Clients need access to the element objects
3. The aggregate object should not expose its internal structure
4. Multiple clients may want independent access
Solution
1. Define an iterator that fetches one element at a time
2. Each iterator object keeps track of the position of the next element
3. If there are several aggregate/iterator variations, it is best if the
aggregate and iterator classes realize common interface types.
Then the client only needs to know the interface types, not the
concrete classes.
30
Iterator Pattern
31
Iterator Pattern
Names in pattern are
examples
Names differ in each
occurrence of pattern
Name in Design Pattern
Actual Name (linked lists)
Aggregate
List
ConcreteAggregate
LinkedList
Iterator
ListIterator
ConcreteIterator
anonymous class implementing ListIterator
createIterator()
listIterator()
next()
next()
isDone()
opposite of hasNext()
currentItem()
return value of hasNext()
32
1.
The ITERATOR as a Pattern
2.
The Pattern Concept and Introduction to GoF Design
Patterns
3. The OBSERVER Pattern
4.
Layout Managers and the STRATEGY Pattern
5.
Components, Containers, and the COMPOSITE Pattern
6.
Scroll Bars and the DECORATOR Pattern
7.
How to Recognize Patterns
8.
Putting Patterns to Work
33
Model/View/Controller
Some
programs have
multiple editable views
Example: HTML Editor
• WYSIWYG view
• structure view
• source view
Editing one view
updates the other
Updates seem
instantaneous
34
HTML Editor: MS FrontPage WYSIWYG view
35
MS FrontPage Source View
36
MS FrontPage Structure (Navigation) View
37
Windows
An example of MVC architecture: The “model” is the filename dp3.ppt. One “view” is a window titled CENG 534
Design Patterns, which displays the contents of a folder containing the file dp3.ppt. The other “view” is window
called dp3.ppt Properties, which displays information related to the file. If the file name is changed, both views
are updated by the “controller”.
38
Model/View/Controller
Model: data structure,
no visual
representation
Views: visual
representations
Controllers: user
interaction
Views/controllers
update model
Model tells views that
data has changed
Views redraw
themselves
MVC is an Architectural Pattern and is not a GoF Pattern.
But it is based on the Observer (Model/View) GoF pattern.
39
Observer Pattern
Model
notifies views when something interesting happens
Button notifies action listeners when something interesting
happens
Views
attach themselves to model in order to be notified
The View(s) display the Model and is notified (via a
subscribe/notify protocol) whenever the Model is changed.
Action listeners attach themselves to button in order to be
notified
Generalize:
Observers attach themselves to subject
Observer is a behavioral GoF Pattern.
40
Observer Pattern
Context
1. An object, called the subject,
is source of events
2. One or more observer
objects want to be notified
when such an event occurs.
Solution
1. Define an observer interface type. All concrete observers
implement it.
2. The subject maintains a collection of observers.
3. The subject supplies methods for attaching and detaching
observers.
4. Whenever an event occurs, the subject notifies all observers.
41
Observer Pattern
Java 1.1 introduced a new GUI event model based on the Observer
Pattern
GUI components which can generate GUI events are called event
sources.
Objects that want to be notified of GUI events are called event
(action) listeners.
Event generation is also called firing the event.
Comparison to the Observer Pattern:
Subject => event source (Example: JButton)
Observer => Action Listener
ConcreteObserver => Action Listener implementation
For an event listener to be notified of an event, it must first register
with the event source.
42
Names in Observer Pattern
Name in Design Pattern
Actual Name (Swing buttons)
Subject
JButton
Observer
ActionListener
ConcreteObserver
the class that implements the
ActionListener interface type
attach()
addActionListener()
notify()
actionPerformed()
43
Observer Pattern (From GoF Books)
Intent
Define a one-to-many dependency between objects so that when one
object changes state, all its dependents are notified and updated
automatically.
Also Known As
Dependents, Publish-Subscribe, Model-View.
Motivation
The need to maintain
consistency between related
objects without making
classes tightly coupled.
44
Applicability
Use the Observer pattern in any of the following situations:
When an abstraction has two aspects, one dependent on the
other. Encapsulating these aspects in separate objects lets
you vary and reuse them independently.
When a change to one object requires changing others
When an object should be able to notify other objects without
making assumptions about those objects
45
Structure (given in GoF DP Book)
46
The Elements of Observer Pattern
Participants
Subject
• Keeps track of its observers
• Provides an interface for attaching and detaching Observer objects
Observer
• Defines an interface for update notification
ConcreteSubject
• The object being observed
• Stores state of interest to ConcreteObserver objects
• Sends a notification to its observers when its state changes
ConcreteObserver
• The observing object
• Stores state that should stay consistent with the subject's
• Implements the Observer update interface to keep its state consistent
with the subject's
47
Consequences
Benefits
Minimal coupling between the Subject and the Observer
• Can reuse subjects without reusing their observers and vice versa
• Observers can be added without modifying the subject
• All subject knows is its list of observers
• Subject does not need to know the concrete class of an observer, just
that each observer implements the update interface
• Subject and observer can belong to different abstraction layers
Support for event broadcasting
• Subject sends notification to all subscribed observers
• Observers can be added/removed at any time
Liabilities
Possible cascading of notifications
• Observers are not necessarily aware of each other and must be
careful about triggering updates
Simple update interface requires observers to deduce changed item
48
Sample Code, Known Uses and Related Patterns
Sample Code
We'll see some Java soon!
Known Uses
Smalltalk Model/View/Controller user interface framework
• Model = Subject
• View = Observer
• Controller is whatever object changes the state of the subject
Related Patterns
Mediator
• To encapsulate complex update semantics
49
Using Design Patterns Templates in
Together for Eclipse Architect 2006
Use Class By Templete or choose any class on the diagram and
apply one of GoF Design Patterns:
50
Select Template and Specify Parameters
51
Observers and Observables Created by Together
Create Pattern Links: unchecked
52
Observers and Observables Created by Together
Create Pattern Links: Checked
53
Files Created by Together: Subject: Vehicle.java
import java.util.ArrayList;
import java.util.Iterator;
/**
* @role __Subject
*/
public class Vehicle {
private ArrayList observers;
/**
* @link
* @shapeType PatternLink
* @pattern gof.Observer
* @supplierRole Abstract Observer
*/
/* # private TrafficControl lnkTrafficControl; */
public void attach(TrafficControl observer) {
observers.add(observer);
}
public void detach(TrafficControl observer) {
observers.remove(observer);
}
public void notifyObservers() {
Iterator it = observers.iterator();
while (it.hasNext()) {
((TrafficControl) it.next()).update(this);
}
}
}
54
Concrete Subjects: Car, Truck, and Van
/**
* Stores state of interest to ConcreteObserver objects.
* Sends a notification to its observers when its state changes.
*/
public class Car extends Vehicle {
}
/**
* Stores state of interest to ConcreteObserver objects.
* Sends a notification to its observers when its state changes.
*/
public class Truck extends Vehicle {
}
/**
* Stores state of interest to ConcreteObserver objects.
* Sends a notification to its observers when its state changes.
*/
public class Van extends Vehicle {
}
55
Traffic Control Interface and Concrete Observers
/**
* @role __Observer
*/
public interface TrafficControl {
/**
* @link
* @shapeType PatternLink
* @pattern gof.Observer
* @supplierRole Abstract Subject
*/
/*# private Vehicle lnkVehicle;*/
void update(Vehicle subject);
}
/**
* Implements the Observer updating interface to keep
* its state consistent with the subject's.
*/
public class HighwayPatrol implements TrafficControl {
public void update(Vehicle subject) {
//put your code here
}
/**
* Implements the Observer updating interface to keep
* its state consistent with the subject's.
*/
public class Sheriff implements TrafficControl {
}
public void update(Vehicle subject) {
//put your code here
}
}
56
Java Implementation of Observer Pattern
We could implement the Observer pattern “from scratch” in Java
But Java provides the Observable/Observer classes as built-in
support for the Observer pattern
The java.util.Observable class is the base Subject class.
Any class that wants to be observed extends this class.
• Provides methods to add/delete observers
• Provides methods to notify all observers
• A subclass only needs to ensure that its observers are notified in
the appropriate mutators
• Uses a Vector for storing the observer references
The java.util.Observer interface is the Observer interface.
It must be implemented by any observer class.
57
The java.util.Observable Class
public Observable()
• Construct an Observable with zero Observers
public synchronized void addObserver(Observer o)
• Adds an observer to the set of observers of this object
public synchronized void deleteObserver(Observer o)
• Deletes an observer from the set of observers of this object
protected synchronized void setChanged()
• Indicates that this object has changed
protected synchronized void clearChanged()
• Indicates that this object has no longer changed, or that it has
already notified all of its observers of its most recent change. This
method is called automatically by notifyObservers().
58
The java.util.Observable Class
public synchronized boolean hasChanged()
• Tests if this object has changed. Returns true if setChanged() has been
called more recently than clearChanged() on this object; false otherwise.
public void notifyObservers(Object arg)
• If this object has changed, as indicated by the hasChanged() method,
then notify all of its observers and then call the clearChanged() method
to indicate that this object has no longer changed. Each observer has its
update() method called with two arguments: this observable object and
the arg argument. The arg argument can be used to indicate which
attribute of the observable object has changed.
public void notifyObservers()
• Same as above, but the arg argument is set to null. That is, the observer
is given no indication what attribute of the observable object has
changed.
59
The java.util.Observer Interface
public abstract void update(Observable o, Object arg)
• This method is called whenever the observed object is changed.
An application calls an observable object's notifyObservers
method to have all the object's observers notified of the change.
• Parameters:
o - the observable object
arg - an argument passed to the notifyObservers method
60
Observable/Observer Example
61
ConcreteSubject.java
import java.util.Observable;
/** A subject to observe! */
public class ConcreteSubject extends Observable {
private String name;
private float price;
public ConcreteSubject(String name, float price) {
this.name = name;
this.price = price;
System.out.println("ConcreteSubject created: " + name + " at " + price);
}
public String getName() { return name; }
public float getPrice() { return price; }
public void setName(String name) {
this.name = name;
setChanged();
notifyObservers(name);
}
public void setPrice(float price) {
this.price = price;
setChanged();
notifyObservers(new Float(price));
}
}
62
Name and Price Observers
import java.util.Observer;
import java.util.Observable;
// An observer of name changes.
public class NameObserver implements Observer {
private String name;
public NameObserver() {
name = null;
System.out.println("NameObserver created: Name is " + name);
}
public void update(Observable obj, Object arg) {
if (arg instanceof String) {
name = (String)arg;
System.out.println("NameObserver: Name changed to " + name);
}
}
}
import java.util.Observer;
import java.util.Observable;
// An observer of price changes.
public class PriceObserver implements Observer {
private float price;
public PriceObserver() {
price = 0;
System.out.println("PriceObserver created: Price is " + price);
}
public void update(Observable obj, Object arg) {
if (arg instanceof Float) {
price = ((Float)arg).floatValue();
System.out.println("PriceObserver: Price changed to " + price);
}
}
}
63
TestObservers.java
import java.util.Observer;
import java.util.Observable;
// Test program for ConcreteSubject, NameObserver and PriceObserver
public class TestObservers {
public static void main(String args[]) {
// Create the Subject and Observers.
ConcreteSubject s = new ConcreteSubject("Corn Pops", 1.29f);
NameObserver nameObs = new NameObserver();
PriceObserver priceObs = new PriceObserver();
// Add those Observers!
s.addObserver(nameObs);
s.addObserver(priceObs);
// Make changes to the Subject.
s.setName("Frosted Flakes");
s.setPrice(4.57f);
s.setPrice(9.22f);
s.setName("Surge Crispies");
}
}
64
A Simple MVC Example: CounterGui
import java.awt.event.*;
import java.awt.*;
Button exitButton = new Button("Exit");
exitButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
buttonPanel.add(exitButton);
public class CounterGui extends Frame {
private int counter = 0;
// Model!
private TextField tf = new TextField(10); // View.
public CounterGui(String title) {
super(title);
Panel tfPanel = new Panel();
tf.setText("0");
tfPanel.add(tf);
add("North", tfPanel);
Panel buttonPanel = new Panel();
add("South", buttonPanel);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
Button incButton = new Button("Increment");
incButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
counter++;
tf.setText(counter + "");
}
});
buttonPanel.add(incButton);
public static void main(String[] argv) {
CounterGui cg = new CounterGui("CounterGui");
cg.setSize(300, 100);
cg.setVisible(true);
}
}
Button decButton = new Button("Decrement");
decButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
counter--;
tf.setText(counter + "");
}
});
buttonPanel.add(decButton);
Where is the controller in this example??
The controllers are the instances of the anonymous classes which handle the button presses.
65
Account System based on MVC Architecture
from Advanced Java 2 Platform,
How to Program, H. M. Deitel)
66
The Class Diagrams of the Account System
67
Sequence of Events
2.User updates accounts
:Controller
3. Request account change in model
1. Views subscribe to event
:Model
5. Updated views
4. Notify subscribers
:AccountTextView
:AccountBarGrapView
:AssetPieChartView
68
1.
The ITERATOR as a Pattern
2.
The Pattern Concept and Introduction to GoF Design
Patterns
3.
The OBSERVER Pattern
4. Layout Managers and the STRATEGY
Pattern
5.
Components, Containers, and the COMPOSITE Pattern
6.
Scroll Bars and the DECORATOR Pattern
7.
How to Recognize Patterns
8.
Putting Patterns to Work
69
Layout Managers
User interfaces made up of components
Components placed in containers
Container needs to arrange components
Swing doesn't use hard-coded pixel coordinates
Advantages:
• Can switch "look and
feel"
• Can internationalize
strings
Layout manager controls
arrangement
70
Using Predefined Layout Managers
There are several built-in layout managers in Java:
FlowLayout: left to right, start new row when full
BoxLayout: left to right or top to bottom
BorderLayout: 5 areas, Center, North, South, East, West
GridLayout: grid, all components have same size
GridBagLayout: complex, like HTML table
71
Layout Managers
72
Layout Managers
Set layout manager
JPanel keyPanel = new JPanel();
keyPanel.setLayout(new GridLayout(4, 3));
Add components
for (int i = 0; i < 12; i++)
keyPanel.add(button[i]);
73
Voice Mail System GUI
Same backend as text-based system
Only Telephone class changes
Buttons for keypad
Text areas for microphone, speaker
74
Voice Mail System GUI
Arrange keys in panel with GridLayout:
JPanel keyPanel = new JPanel();
keyPanel.setLayout(new GridLayout(4, 3));
for (int i = 0; i < 12; i++)
{ JButton keyButton = new JButton(...);
keyPanel.add(keyButton);
keyButton.addActionListener(...);
}
75
Voice Mail System GUI
Panel with BorderLayout for speaker
JPanel speakerPanel = new JPanel();
speakerPanel.setLayout(new BorderLayout());
speakerPanel.add(new JLabel("Speaker:"),
BorderLayout.NORTH);
speakerField = new JTextArea(10, 25);
speakerPanel.add(speakerField, BorderLayout.CENTER);
76
Voice Mail System GUI
Put speaker, keypads, and microphone panel into content pane
Content pane already has BorderLayout
Ch5/mailgui/Telephone.java
77
Telephone.java (1)
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
// Presents a phone GUI for the voice mail system.
public class Telephone
{
// Constructs a telephone with a speaker, keypad, and microphone.
public Telephone()
{
JPanel speakerPanel = new JPanel();
speakerPanel.setLayout(new BorderLayout());
speakerPanel.add(new JLabel("Speaker:"), BorderLayout.NORTH);
speakerField = new JTextArea(10, 25);
speakerPanel.add(speakerField, BorderLayout.CENTER);
String keyLabels = "123456789*0#";
JPanel keyPanel = new JPanel();
keyPanel.setLayout(new GridLayout(4, 3));
for (int i = 0; i < keyLabels.length(); i++)
{
final String label = keyLabels.substring(i, i + 1);
JButton keyButton = new JButton(label);
keyPanel.add(keyButton);
keyButton.addActionListener(new
ActionListener()
{
public void actionPerformed(ActionEvent event)
{
connect.dial(label);
}
});
}
…..
78
Telephone.java (2)
final JTextArea microphoneField = new JTextArea(10,25);
JButton speechButton = new JButton("Send speech");
speechButton.addActionListener(new
ActionListener()
{
public void actionPerformed(ActionEvent event)
{
connect.record(microphoneField.getText());
microphoneField.setText("");
}
});
JButton hangupButton = new JButton("Hangup");
hangupButton.addActionListener(new
ActionListener()
{
public void actionPerformed(ActionEvent event)
{
connect.hangup();
}
});
…..
79
Telephone.java (3)
JPanel buttonPanel = new JPanel();
buttonPanel.add(speechButton);
buttonPanel.add(hangupButton);
JPanel microphonePanel = new JPanel();
microphonePanel.setLayout(new BorderLayout());
microphonePanel.add(new JLabel("Microphone:"), BorderLayout.NORTH);
microphonePanel.add(microphoneField, BorderLayout.CENTER);
microphonePanel.add(buttonPanel, BorderLayout.SOUTH);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(speakerPanel, BorderLayout.NORTH);
frame.add(keyPanel, BorderLayout.CENTER);
frame.add(microphonePanel, BorderLayout.SOUTH);
frame.pack();
frame.setVisible(true);
}
// Give instructions to the mail system user.
public void speak(String output)
{
speakerField.setText(output);
}
public void run(Connection c)
{
connect = c;
}
private JTextArea speakerField;
private Connection connect;
}
80
Implementing a Custom Layout Manager
It is not a difficult to write your own layout manager
Form layout
Odd-numbered components right aligned
Even-numbered components left aligned
Implement LayoutManager interface type
81
The LayoutManager Interface Type
public interface LayoutManager
{ void layoutContainer(Container parent);
Dimension minimumLayoutSize(Container parent);
Dimension preferredLayoutSize(Container parent);
void addLayoutComponent(String name, Component comp);
void removeLayoutComponent(Component comp);
}
Ch5/layout/FormLayout.java
Ch5/layout/FormLayoutTester.java
Note: Can use GridBagLayout to achieve the same effect
82
FormLayout.java (1)
import java.awt.*;
/**
A layout manager that lays out components along a central axis
*/
public class FormLayout implements LayoutManager
{
public Dimension preferredLayoutSize(Container parent)
{
Component[] components = parent.getComponents();
left = 0;
right = 0;
height = 0;
for (int i = 0; i < components.length; i += 2)
{
Component cleft = components[i];
Component cright = components[i + 1];
Dimension dleft = cleft.getPreferredSize();
Dimension dright = cright.getPreferredSize();
left = Math.max(left, dleft.width);
right = Math.max(right, dright.width);
height = height + Math.max(dleft.height, dright.height);
}
return new Dimension(left + GAP + right, height);
}
public Dimension minimumLayoutSize(Container parent)
{
return preferredLayoutSize(parent);
}
…..
83
FormLayout.java (2)
public void layoutContainer(Container parent)
{
preferredLayoutSize(parent); // Sets left, right
Component[] components = parent.getComponents();
Insets insets = parent.getInsets();
int xcenter = insets.left + left;
int y = insets.top;
for (int i = 0; i < components.length; i += 2)
{
Component cleft = components[i];
Component cright = components[i + 1];
Dimension dleft = cleft.getPreferredSize();
Dimension dright = cright.getPreferredSize();
int height = Math.max(dleft.height, dright.height);
cleft.setBounds(xcenter - dleft.width, y + (height - dleft.height) / 2, dleft.width, dleft.height);
cright.setBounds(xcenter + GAP, y + (height - dright.height) / 2, dright.width, dright.height);
y += height;
}
}
public void addLayoutComponent(String name, Component comp) {}
public void removeLayoutComponent(Component comp) {}
private int left;
private int right;
private int height;
private static final int GAP = 6;
}
84
FormLayoutTester.java
import java.awt.*;
import javax.swing.*;
public class FormLayoutTester
{
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.setLayout(new FormLayout());
frame.add(new JLabel("Name"));
frame.add(new JTextField(15));
frame.add(new JLabel("Address"));
frame.add(new JTextField(20));
frame.add(new JLabel("City"));
frame.add(new JTextField(10));
frame.add(new JLabel("State"));
frame.add(new JTextField(2));
frame.add(new JLabel("ZIP"));
frame.add(new JTextField(5));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}
85
Strategy Pattern
Pluggable
strategy for layout management
Layout manager object responsible for executing concrete
strategy
Generalizes to Strategy Design Pattern
The strategy pattern applies whenever you want to allow a
client to support an algorithm.
It is a behavioral pattern for selecting one of many algorithms
86
Strategy Pattern
Context
1. A class can benefit from different variants for an
algorithm
2. Clients sometimes want to replace standard
algorithms with custom versions
Solution
1. Define an interface type that is an abstraction for the algorithm
2. Actual strategy classes realize this interface type.
3. Clients can supply strategy objects
4. Whenever the algorithm needs to be executed, the context class
calls the appropriate methods of the strategy object
87
Strategy Pattern Example: Layout Management
The relationships between the
names in the Strategy Pattern
and the layout management
manifestation:
Name in Design Pattern
Actual Name (layout management)
Context
Container
Strategy
LayoutManager
ConcreteStrategy
a layout manager such as BorderLayout
doWork()
a method such as layoutContainer
88
Strategy Pattern Example: Sorting
Other manifestation: Comparators
Comparator<Country> comp = new CountryComparatorByName();
Collections.sort(countries, comp);
Name in Design Pattern
Actual Name (sorting)
Context
Collections
Strategy
Comparator
ConcreteStrategy
a class that implements Comparator
89
1.
The ITERATOR as a Pattern
2.
The Pattern Concept and Introduction to GoF Design
Patterns
3.
The OBSERVER Pattern
4.
Layout Managers and the STRATEGY Pattern
5. Components, Containers, and the
COMPOSITE Pattern
6.
Scroll Bars and the DECORATOR Pattern
7.
How to Recognize Patterns
8.
Putting Patterns to Work
90
Containers and Components
Containers
collect GUI components
Sometimes, want to add a container to another container
Container should be a component
Composite design pattern
Composite method typically invoke component methods
E.g. Container.getPreferredSize invokes
getPreferredSize of components
It
is a structural pattern for building recursive aggregations
91
Composite Pattern
Context
1. Primitive objects can
be combined to
composite objects
2. Clients treat a
composite object as
a primitive object
Solution
1. Define an interface type that is an abstraction for the primitive
objects
2. Composite object collects primitive objects
3. Composite and primitive classes implement same interface type.
4. When implementing a method from the interface type, the
composite class applies the method to its primitive objects and
combines the results
92
Composite Pattern Example in Java
Name in Design Pattern
Actual Name (AWT components)
Primitive
Component
Composite
Container
Leaf
a component without children (e.g. JButton)
method()
a method of Component (e.g.getPreferredSize)
93
1.
The ITERATOR as a Pattern
2.
The Pattern Concept and Introduction to GoF Design
Patterns
3.
The OBSERVER Pattern
4.
Layout Managers and the STRATEGY Pattern
5.
Components, Containers, and the COMPOSITE Pattern
6. Scroll Bars and the DECORATOR Pattern
7.
How to Recognize Patterns
8.
Putting Patterns to Work
94
Scroll Bars
Scroll bars can be attached to components
Approach #1: Component class can turn on scroll bars
Approach #2: Scroll bars can surround component
JScrollPane pane = new JScrollPane(component);
Swing uses approach #2
JScrollPane is again a component
It is a structural pattern for extending an object transparently
95
Decorator Pattern - Context
Context
1. Component objects can be decorated (visually or behaviorally
enhanced)
2. The decorated object can be used in the same way as the
undecorated object
3. The component class does not want to take on the responsibility of
the decoration
4. There may be an open-ended set of possible decorations
96
Decorator Pattern - Solution
Solution
1. Define an interface type that is an abstraction for the component
2. Concrete component classes realize this interface type.
3. Decorator classes also realize this interface type.
4. A decorator object manages the component object that it decorates
5. When implementing a method from the component interface type, the
decorator class applies the method to the decorated component and
combines the result with the effect of the decoration.
97
Decorator Pattern Example: Scroll Bars
Name in Design Pattern
Actual Name (scroll bars)
Component
Component
ConcreteComponent
JTextArea
Decorator
JScrollPane
method()
a method of Component (e.g. paint)
98
Decorator Pattern Example: Streams
InputStreamReader reader = new InputStreamReader(System.in);
BufferedReader console = new BufferedReader(reader);
BufferedReader takes a Reader and adds buffering
Result is another Reader: Decorator pattern
Many other decorators in stream library, e.g. PrintWriter
Name in Design Pattern
Actual Name (input streams)
Component
Reader
ConcreteComponent
InputStreamReader
Decorator
BufferedReader
method()
read
99
1.
The ITERATOR as a Pattern
2.
The Pattern Concept and Introduction to GoF Design
Patterns
3.
The OBSERVER Pattern
4.
Layout Managers and the STRATEGY Pattern
5.
Components, Containers, and the COMPOSITE Pattern
6.
Scroll Bars and the DECORATOR Pattern
7. How to Recognize Patterns
8.
Putting Patterns to Work
100
How to Recognize Patterns
Look
at the intent of the pattern
E.g. COMPOSITE has different intent than DECORATOR
Remember common uses (e.g. STRATEGY for layout
managers)
Not everything that is strategic is an example of STRATEGY
pattern
Use
context and solution as "litmus test"
101
Litmus Test
Add border to Swing component
Border b = new EtchedBorder();
component.setBorder(b);
Undeniably decorative
Is it an example of DECORATOR?
102
Litmus Test
1. Component objects can be decorated (visually or behaviorally
enhanced)
PASS
2. The decorated object can be used in the same way as the
undecorated object
PASS
3. The component class does not want to take on the responsibility of
the decoration
FAIL--the component class has setBorder method
4. There may be an open-ended set of possible decorations
103
1.
The ITERATOR as a Pattern
2.
The Pattern Concept and Introduction to GoF Design
Patterns
3.
The OBSERVER Pattern
4.
Layout Managers and the STRATEGY Pattern
5.
Components, Containers, and the COMPOSITE Pattern
6.
Scroll Bars and the DECORATOR Pattern
7.
How to Recognize Patterns
8. Putting Patterns to Work
104
Putting Patterns to Work
Invoice contains line items
Line item has description, price
Interface type LineItem:
Ch5/invoice/LineItem.java
Product is a concrete class that implements this interface:
Ch5/invoice/Product.java
105
LineItem.java and Product.java
/**
A line item in an invoice.
*/
public interface LineItem
{
/**
Gets the price of this line item.
@return the price
*/
double getPrice();
/**
Gets the description of this line item.
@return the description
*/
String toString();
}
/**
A product with a price and description.
*/
public class Product implements LineItem
{
/**
Constructs a product.
@param description the description
@param price the price
*/
public Product(String description, double price)
{
this.description = description;
this.price = price;
}
public double getPrice() { return price; }
public String toString() { return description; }
private String description;
private double price;
}
106
Bundles
Bundle = set of related items with description+price
E.g. stereo system with tuner, amplifier, CD player + speakers
A bundle has line items
A bundle is a line item
COMPOSITE pattern
Ch5/invoice/Bundle.java (look at getPrice)
107
Bundle.java
import java.util.*;
// A bundle of line items that is again a line item.
public class Bundle implements LineItem
{
// Constructs a bundle with no items.
public Bundle() { items = new ArrayList<LineItem>(); }
/**
Adds an item to the bundle.
@param item the item to add
*/
public void add(LineItem item) { items.add(item); }
public double getPrice()
{
double price = 0;
for (LineItem item : items)
price += item.getPrice();
return price;
}
public String toString()
{
String description = "Bundle: ";
for (int i = 0; i < items.size(); i++)
{
if (i > 0) description += ", ";
description += items.get(i).toString();
}
return description;
}
private ArrayList<LineItem> items;
}
108
Discounted Items
Store may give discount for an item
Discounted item is again an item
DECORATOR pattern
Ch5/invoice/DiscountedItem.java (look at getPrice)
Alternative design: add discount to LineItem
109
DiscountedItem.java
/**
A decorator for an item that applies a discount.
*/
public class DiscountedItem implements LineItem
{
/**
Constructs a discounted item.
@param item the item to be discounted
@param discount the discount percentage
*/
public DiscountedItem(LineItem item, double discount)
{
this.item = item;
this.discount = discount;
}
public double getPrice()
{
return item.getPrice() * (1 - discount / 100);
}
public String toString()
{
return item.toString() + " (Discount " + discount
+ "%)";
}
private LineItem item;
private double discount;
}
110
Model/View Separation
GUI has commands to add items to invoice
GUI displays invoice
Decouple input from display
Display wants to know when invoice is modified
Display doesn't care which command modified invoice
OBSERVER pattern
111
Change Listeners
Use standard ChangeListener interface type
public interface ChangeListener
{
void stateChanged(ChangeEvent event);
}
Invoice collects ArrayList of change listeners
When the invoice changes, it notifies all listeners:
ChangeEvent event = new ChangeEvent(this);
for (ChangeListener listener : listeners)
listener.stateChanged(event);
112
Change Listeners
Display adds itself as a change listener to the invoice
Display updates itself when invoice object changes state
final Invoice invoice = new Invoice();
final JTextArea textArea = new JTextArea(20, 40);
ChangeListener listener = new
ChangeListener()
{ public void stateChanged(ChangeEvent event)
{ textArea.setText(...);
}
};
113
Observing the Invoice
114
Iterating Through Invoice Items
Invoice collect line items
Clients need to iterate over line items
Don't want to expose ArrayList
May change (e.g. if storing invoices in database)
ITERATOR pattern
115
Iterators
Use standard Iterator interface type
public interface Iterator<LineItem>
{ boolean hasNext();
LineItem next();
void remove();
}
remove is "optional operation" (see ch. 8)
implement to throw UnsupportedException
implement hasNext/next manually to show inner workings
Ch5/invoice/Invoice.java
116
Invoice.java (1)
import java.util.*;
import javax.swing.event.*;
// An invoice for a sale, consisting of line items.
public class Invoice
{
// Constructs a blank invoice.
public Invoice()
{
items = new ArrayList<LineItem>();
listeners = new ArrayList<ChangeListener>();
}
/**
Adds an item to the invoice.
@param item the item to add
*/
public void addItem(LineItem item)
{
items.add(item);
// Notify all observers of the change to the invoice
ChangeEvent event = new ChangeEvent(this);
for (ChangeListener listener : listeners)
listener.stateChanged(event);
}
/**
Adds a change listener to the invoice.
@param listener the change listener to add
*/
public void addChangeListener(ChangeListener listener)
{
listeners.add(listener);
}
….
117
Invoice.java (2)
/**
Gets an iterator that iterates through the items.
@return an iterator for the items
*/
public Iterator<LineItem> getItems()
{
return new
Iterator<LineItem>()
{
public boolean hasNext()
{ return current < items.size(); }
public LineItem next()
{ return items.get(current++); }
public void remove()
{ throw new UnsupportedOperationException(); }
private int current = 0;
};
}
public String format(InvoiceFormatter formatter)
{
String r = formatter.formatHeader();
Iterator<LineItem>iter = getItems();
while (iter.hasNext())
r += formatter.formatLineItem(iter.next());
return r + formatter.formatFooter();
}
private ArrayList<LineItem> items;
private ArrayList<ChangeListener> listeners;
}
118
Formatting Invoices
Simple format: dump into text area
May not be good enough,
E.g. HTML tags for display in browser
Want to allow for multiple formatting algorithms
STRATEGY pattern
119
InvoiceFormatter.java
/**
This interface describes the tasks that an invoice
formatter needs to carry out.
*/
public interface InvoiceFormatter
{
/**
Formats the header of the invoice.
@return the invoice header
*/
String formatHeader();
/**
Formats a line item of the invoice.
@return the formatted line item
*/
String formatLineItem(LineItem item);
/**
Formats the footer of the invoice.
@return the invoice footer
*/
String formatFooter();
}
120
SimpleFormatter.java
/**
A simple invoice formatter.
*/
public class SimpleFormatter implements InvoiceFormatter
{
public String formatHeader()
{
total = 0;
return " I N V O I C E\n\n\n";
}
public String formatLineItem(LineItem item)
{
total += item.getPrice();
return (String.format(
"%s: $%.2f\n",item.toString(),item.getPrice()));
}
public String formatFooter()
{
return (String.format("\n\nTOTAL DUE: $%.2f\n", total));
}
private double total;
}
121
InvoiceTester.java (1)
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
// A program that tests the invoice classes.
public class InvoiceTester
{
public static void main(String[] args)
{ final Invoice invoice = new Invoice();
final InvoiceFormatter formatter = new SimpleFormatter();
// This text area will contain the formatted invoice
final JTextArea textArea = new JTextArea(20, 40);
// When the invoice changes, update the text area
ChangeListener listener = new
ChangeListener()
{
public void stateChanged(ChangeEvent event)
{
textArea.setText(invoice.format(formatter));
}
};
invoice.addChangeListener(listener);
// Add line items to a combo box
final JComboBox combo = new JComboBox();
Product hammer = new Product("Hammer", 19.95);
Product nails = new Product("Assorted nails", 9.95);
combo.addItem(hammer);
Bundle bundle = new Bundle();
bundle.add(hammer);
bundle.add(nails);
combo.addItem(new DiscountedItem(bundle, 10));
…
122
InvoiceTester.java
// Make a button for adding the currently selected
// item to the invoice
JButton addButton = new JButton("Add");
addButton.addActionListener(new
ActionListener()
{
public void actionPerformed(ActionEvent event)
{
LineItem item = (LineItem) combo.getSelectedItem();
invoice.addItem(item);
}
});
// Put the combo box and the add button into a panel
JPanel panel = new JPanel();
panel.add(combo);
panel.add(addButton);
// Add the text area and panel to the content pane
JFrame frame = new JFrame();
frame.add(new JScrollPane(textArea),
BorderLayout.CENTER);
frame.add(panel, BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}
123
Formatting Invoices
124
Formatting Invoices
125
References
•
This lecture is mainly based on the book Object Oriented Design and
Patterns [1].
•
There are also some slides adapted from various resources and my own
slides. They are cited below:
Main Resources:
1. C. Horstmann, Object Oriented Design and Patterns (OODP), 2nd
Edition,, John Wiley, ISBN: 0-471-74487-5, 2005.
2. E. Gamma, R. Helm, R. Johnson, J. Vlissides, Design Patterns, Elements
of Reusable Object-Oriented Software, Addison-Wesley, 1995.
3. Lecture notes of CENG 535/410 Design Patterns course at Fatih
University:
http://www.fatih.edu.tr/~haluk/Teaching/Fatih/2003%20Fall/ceng%20534/ce
ng534-2003.htm
126