Lecture09 Design Patterns 1
Lecture09 Design Patterns 1
Design Patterns
Outline
Slide 2
What is a design pattern?
Slide 3
Example 1: Encapsulation (data hiding)
Slide 4
Example 2: Subclassing (inheritance)
Slide 5
Example 3: Iteration
Slide 6
Example 4: Exceptions
Problem:
Errors in one part of the code should be handled elsewhere.
Code should not be cluttered with error-handling
error handling code.
code
Return values should not be preempted by error codes.
Solution: Language
g g structures for throwingg and catchingg
exceptions
Disadvantages:
C d may still
Code ill be
b cluttered.
l d
It may be hard to know where an exception will be
handled.
Use of exceptions for normal control flow may be
confusing and inefficient.
Slide 7
Example 5: Generics
Problem:
Well-designed data structures hold one type of object
Solution:
Programming language checks for errors in contents
List<Date> instead of jjust List
Disadvantages:
Slightly more verbose types
Slide 8
Creating generic classes
Slide 9
Tips for designing generic classes
Slide 10
A puzzle about generics
Slide 11
When (not) to use design patterns
Slide 12
Why should you care?
Slide 13
Creational patterns
Factories
Factory method
Factory object
Prototype
Sharing
Singleton
Interning
Flyweight
Slide 14
Factories
Slide 15
Motivation for factories: Changing implementations
Slide 16
Use of factories
Factory
class MatrixFactory {
public static Matrix createMatrix() {
return new SparseMatrix();
}
}
Clients call createMatrix, not a particular constructor
Advantages
Ad
To switch the implementation, only change one place
Can decide what type
yp of matrix to create
Slide 17
Example: bicycle race
class Race {
// factory method
Race createRace() {
...
}
Slide 18
Example: Tour de France
// factory method
Race createRace() {
Bicycle bike1 = new RoadBicycle();
Bicycle bike2 = new RoadBicycle();
...
}
Slide 19
Example: Cyclocross
// factory method
Race createRace() {
Bicycle bike1 = new MountainBicycle();
Bicycle bike2 = new MountainBicycle();
...
}
Slide 20
Factory method for Bicycle
class Race {
Bicycle createBicycle() { ... }
Race createRace() {
y
Bicycle bike1 = createBicycle();
y ();
Bicycle bike2 = createBicycle();
...
}
}
Slide 21
Code using factory methods
class Race {
Bicycle createBicycle() { ... }
Race createRace() {
y
Bicycle bike1 = createBicycle();
y ();
Bicycle bike2 = createBicycle();
...
}
}
class TourDeFrance extends Race {
Bicycle createBicycle() {
y ();
return new RoadBicycle();
}
}
y
class Cyclocross extends Race {
Bicycle createBicycle(Frame) {
return new MountainBicycle();
}
}
Slide 22
Factory objects/classes encapsulate factory methods
class BicycleFactory {
Bicycle createBicycle() { ... }
Frame createFrame() { ... }
Wheel createWheel() { ... }
...
}
class Race {
BicycleFactory bfactory;
// constructor
Race() { bfactory = new BicycleFactory(); }
Race createRace() {
Bicycle bike1 = bfactory.createBicycle();
Bicycle bike2 = bfactory.createBicycle();
...
}
}
Slide 24
Separate control over bicycles and races
class Race {
BicycleFactory bfactory;
// constructor
Race(Bic cleFactor bfactory)
Race(BicycleFactory bfactor ) { this
this.bfactory
bfactor = bfactory;
bfactor }
Race createRace() {
Bicycle bike1 = bfactory.completeBicycle();
Bicycle bike2 = bfactory.completeBicycle();
...
}
}
// No special constructor for TourDeFrance or for Cyclocross
Slide 25
DateFormat factory methods
D t F
DateFormat
t df1 = DateFormat.getDateInstance();
D t F t tD t I t ()
DateFormat df2 = DateFormat.getTimeInstance();
DateFormat df3 = DateFormat.getDateInstance(DateFormat.FULL,
Locale.FRANCE);
l C )
Date today = new Date();
System.out.println(df1.format(today)); // “Jul 4, 1776"
System.out.println(df2.format(today)); // "10:15:00 AM"
System.out.println(df3.format(today)); // “juedi 4 juillet 1776"
Slide 26
Prototype pattern
class Bicyle
y {
Bicycle clone() { ... }
}
Slide 27
Using prototypes
class Race {
Bicycle bproto;
// constructor
Race(Bic cle bproto) { this
Race(Bicycle this.bproto
bproto = bproto
bproto; }
Race createRace() {
Bicycle bike1 = (Bicycle) bproto.clone();
Bicycle bike2 = (Bicycle) bproto.clone();
...
}
}
Slide 28
Sharing
class
l B
Bank
k {
private static bank theBank;
// p
private constructor
private Bank() { ... }
// factory method
public static getBank() {
if (theBank == null) {
theBank = new Bank();
}
return theBank;
}
...
}
Slide 30
Interning pattern
Reuse existing
R i i objects
bj i
instead
d off creating
i new ones
Less space
Mayy compare
p with == instead of equals()
Permitted only for immutable objects
1-100
(Street-
NumberSet)
"Mass Ave"
(Street- "Mass Ave" (String)
Segment) (String) StreetSegment
with interning 1-100
"O2139" (Street-
(String) NumberSet)
(Street-
StreetSegment Segment)
101-200
without interning 101-200 (Street-
(Street- NumberSet)
NumberSet) (Street-
Segment)
(Street- "Mass Ave"
Segment) (String) "O2139"
(String)
"O2139"
(String)
Slide 31
Interning mechanism
Slide 33
Recognition of the problem
Slide 34
Flyweight pattern
Slide 35
Example without flyweight: bicycle spoke
class
l Wh
Wheel
l {
FullSpoke[] spokes;
...
}
class FullSpoke {
int length;
int diameter;
bool tapered;
Metal material;
float weight;
float threading;
bool crimped;
int location; // rim and hub holes this is installed in
}
Slide 36
Alternatives to FullSpoke
class
l I
IntrinsicSpoke
t i i S k {
int length;
int diameter;
boolean tapered;
Metal material;
float weight;
float threading;
boolean crimped;
}
This doesn't work: it's the same as FullSpoke
class InstalledSpokeFull extends IntrinsicSpoke {
int location;
}
This works,
works but flyweight version uses even less space
class InstalledSpokeWrapper {
IntrinsicSpoke s; // refer to interned object
int location;
}
Slide 37
Original code to true (align) a wheel
class FullSpoke {
// Tension the spoke by turning the nipple the
// specified number of turns.
void
oid tighten(int turns)
t rns) {
... location ... // location is a field
}
}
class Wheel {
FullSpoke[] spokes;
void align() {
while (wheel is misaligned) {
// tension the ith spoke
... spokes[i].tighten(numturns) ...
}
}
}
Slide 38
Flyweight code to true (align) a wheel
class IntrinsicSpoke {
void tighten(int turns, int location) {
... location ... // location is a parameter
}
}
class Wheel {
IntrinsicSpoke[] spokes;
void align() {
while (wheel is misaligned) {
// tension the ith spoke
... spokes[i].tighten(numturns, i) ...
}
}
}
Slide 39
Flyweight discussion
Slide 40