0% found this document useful (0 votes)
6 views

Design Patterns Bloch

Uploaded by

mcknucklecuck
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views

Design Patterns Bloch

Uploaded by

mcknucklecuck
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 56

Principles of Software Construction:

Objects, Design, and Concurrency

23 Patterns in 80 Minutes: a Whirlwind Java-centric Tour


of the Gang-of-Four Design Patterns

Josh Bloch Charlie Garrod

17-214 1
Administrivia

• Homework 6 due tomorrow (Wednesday) 11:59 pm EST


• Final exam review session Wednesday, May 12th, 7-9 p.m. EDT
– Practice problems coming out later this week
• Final exam
- Released Thursday, May 13th (evening EDT)
- Due Friday, May 14th, 11:59 p.m. EDT
- Designed to take 3 hrs.
- Open book, open notes, open Internet
- Closed person, no interaction with others about the exam

17-214 2
Outline

I. Creational Patterns
II. Structural Patterns
III. Behavioral Patterns

17-214 3
Pattern Name

• Intent – the aim of this pattern


• Use case – a motivating example
• Types – the key types that define pattern
– Italic type name indicates an abstract class; typically this is an interface
type when the pattern is used in Java
• JDK – example(s) of this pattern in the JDK

17-214 4
Illustration

• Code sample, diagram, or drawing


– Time constraints make it impossible to include illustrations from some
patterns

17-214 5
I. Creational Patterns

1. Abstract factory
2. Builder
3. Factory method
4. Prototype
5. Singleton

17-214 6
1. Abstract Factory

• Intent – allow creation of families of related objects


independent of implementation
• Use case – look-and-feel in a GUI toolkit
– Each look-and-feel has its own windows, scrollbars, etc.
• Types – AbstractFactory with methods to create each family
member; AbstractProducts, the family members themselves;
(ConcreteFactories and ConcreteProducts)
• JDK – not common

17-214 7
GoF Abstract Factory Illustration

Products
WidgetFactory Client
CreateWindow() Window
CreateScrollBar()

PMWindow MotifWindow

MotifWidgetFactory PMWidgetFactory
CreateWindow() CreateWindow()
CreateScrollBar() CreateScrollBar()
ScrollBar

PMScrollBar MotifScrollBar

17-214 8
2. Builder

• Intent – separate construction of a complex object from its


representation so the same creation process can create different
representations
• Use case – converting rich text to various formats
• Types – Builder, ConcreteBuilders, Director, Products
• JDK – StringBuilder, StringBuffer (sorta)
– But there is no (visible) abstract supertype…
– And both generate same product class (String)

17-214 9
GoF Builder Illustration

Director
Builders
RTFReader TextConverter
ParseRTF() AddChar(char)
SetFont(font)
AddParagraph()
while(t = nextToken) {
switch t Type {
CHAR: ASCIIConverter TeXConverter GUITextConverter
builder->AddChar(t.Char) AddChar(char) AddChar(char) AddChar(char)
FONT: GetASCIIText() SetFont(font) SetFont(font)
builder->SetFont(t.Font) AddParagraph() AddParagraph()
PARA: GetTeXText() GetGUIText()
builder->AddParagraph()
}
}
ASCIIText TeXText GUIText

Products
17-214 10
My take on Builder [Effective Java Item 2]

• Emulates named optional parameters in languages that don’t


support them
• Emulates 2n constructors or factories with only n builder methods
• Emulates variable arity parameter lists (varargs) in languages that don’t
support them, and provides better type-safety in languages that do
• Cost is an intermediate (Builder) object
• Not the same as GoF pattern, but related

Pizza largeHawaiian =
new Pizza.Builder(LARGE).add(HAM).add(PINEAPPLE).build();

17-214 11
3. Factory Method

• Intent – abstract creational method that lets subclasses decide


which class to instantiate
• Use case – creating documents in a framework
• Types – Creator, contains abstract method to create an instance
• JDK – SortedMap.subMap​ (K fromKey, K toKey)
– TreeMap, SkipListConcurrentMap return different implementations
• Related Static Factory pattern is very common in Java
– Technically not a GoF pattern, but close enough

17-214 12
Factory Method Illustration

public interface SortedMap<K,V> {


...
SortedMap<K,V> subMap​
(K fromKey, K toKey);
}

public class TreeMap<K,V> implements SortedMap<K,V> {


...
SortedMap<K,V> subMap​
(K fromKey, K toKey) { ... }
...
}

public class ConcurrentSkipListMap<K,V> implements SortedMap<K,V> {


SortedMap<K,V> subMap​
(K fromKey, K toKey) { ... }
...
}

SortedMap<K,V> dictionary = ...;

SortedMap<K,V> firstHalf = dictionary.submap("A", "M");

17-214 13
4. Prototype

• Intent – create an object by cloning another and tweaking


• Use case – writing music score editor in graphical editor framework
• Types – Prototype
• JDK – Cloneable, but avoid (except on arrays)
– Java and Prototype pattern are a poor fit
– Or maybe I just don’t like the pattern, because it only works for mutable types

17-214 14
5. Singleton

• Intent – ensure that a class has only one instance


• Use case – GoF say print queue, file system, company in an
accounting system
– Compelling uses are rare but they do exist
– e.g., stateless function objects, the EmptySet
• Types – Singleton
• JDK – java.lang.Runtime

17-214 15
Singleton Illustration

public enum Elvis {


ELVIS;

sing(Song song) { ... }

playGuitar(Riff riff) { ... }

eat(Food food) { ... }

take(Drug drug) { ... }


}

// Alternative implementation
public class Elvis {
public static final Elvis ELVIS = new Elvis();
private Elvis() { }
...
}

17-214 16
My take on Singleton

• It’s an instance-controlled class; others include


– Static utility class – non-instantiable
– Enum – one instance per value, all values known at compile time
– Interned class – one canonical instance per value, new values created at runtime
• There is a duality between singleton and static utility class

17-214 17
II. Structural Patterns

1. Adapter
2. Bridge
3. Composite
4. Decorator
5. Façade
6. Flyweight
7. Proxy

17-214 18
1. Adapter

• Intent – convert interface of a class into one that is required by


another class, allowing interoperability
• Use case – numerous, e.g., arrays vs. collections
• Types – Target (what you need), Adaptee (what you have),
Adapter (class that implements Target atop Adaptee)
• JDK – Arrays.asList(T[])

17-214 19
Adapter Illustration

Have this and this? Use this!

17-214 20
2. Bridge

• Intent – decouple an abstraction from its implementation so


they can vary independently
• Use case – portable windowing toolkit
• Types – Abstraction, Implementor
• JDK – Java Database Connectivity (JDBC), Java Cryptography
Extension (JCE), Java Naming & Directory Interface (JNDI)
• Bridge pattern very similar to Service Provider (not a GoF pattern)
– Abstraction ~ API, Implementer ~ SPI

17-214 21
Bridge Illustration

17-214 22
3. Composite

• Intent – compose objects into tree structures. Let clients treat


primitives & compositions uniformly.
• Use case – GUI toolkit (widgets and containers)
• Key type – Component that represents both primitives and their
containers
• JDK – javax.swing.JComponent

17-214 23
Composite Illustration

public interface Expression {


double eval(); // Returns value
String toString(); // Returns infix expression string
}

public class UnaryOperationExpression implements Expression {


public UnaryOperationExpression(
UnaryOperator operator, Expression operand);
}
public class BinaryOperationExpression implements Expression {
public BinaryOperationExpression(BinaryOperator operator,
Expression operand1, Expression operand2);
}
public class NumberExpression implements Expression {
public NumberExpression(double number);
}

17-214 24
4. Decorator

• Intent – attach features to an object dynamically


• Use case – attaching borders in a GUI toolkit
• Types – Component, implemented by decorator and decorated
• JDK – Collections (e.g., Unmodifiable wrappers), java.io
streams, Swing components

17-214 25
GoF Decorator Illustration

17-214 26
5. Façade

• Intent – provide a simple unified interface to a complex set of


interfaces in a subsystem
– GoF allow for variants where complex underpinnings are exposed and hidden
• Use case – any complex system; GoF use compiler
• Types – Façade (the simple unified interface)
• JDK – java.util.concurrent.Executors

17-214 27
Façade Illustration

Subsystem classes Façade

√ √ √

√ √ √

17-214 28
6. Flyweight

• Intent – use sharing to support large numbers of fine-grained


immutable objects efficiently
• Use case – characters in a document
• Types – Flyweight (instance-controlled)
– Some state can be extrinsic to reduce number of instances
• JDK – Common! All enums, many others
– j.u.c.TimeUnit has long number-of-units as extrinsic state

17-214 29
GoF Flyweight Illustration

17-214 30
7. Proxy

• Intent – Use one object as a surrogate for another object


• Use case – delay loading of images till needed
• Types – Subject, Proxy, RealSubject
• Gof mention several flavors
– virtual proxy – stand-in that instantiates lazily
– remote proxy – local representative for remote obj
– protection proxy – denies some operations to some users
– smart reference – does locking or reference counting atop real subject
• JDK – RMI (remote proxy), collection wrappers (Unmodifiable
is protection proxy, Synchronized is smart reference)

17-214 31
Proxy Illustrations

Virtual Proxy
aTextDocument
anImageProxy
image anImage
fileName
data
in memory
on disk

Smart Reference Remote Proxy

Client
Server

Proxy

SynchronizedList ArrayList

17-214 32
III. Behavioral Patterns

1. Chain of Responsibility
2. Command
3. Interpreter
4. Iterator
5. Mediator
6. Memento
7. Observer
8. State
9. Strategy
10. Template method
11. Visitor

17-214 33
1. Chain of Responsibility

• Intent – avoid coupling sender to receiver by passing request


along until someone handles it
• Use case – context-sensitive help facility
• Types – RequestHandler
• JDK – ClassLoader, Properties (FWIW)
• Exception handling could be considered a form of Chain of
Responsibility pattern

17-214 34
2. Command

• Intent – encapsulate a request as as an object, letting you


parameterize one action with another, queue or log requests, etc.
• Use case – menu tree
• Key type – Command (in Java, Runnable)
• JDK – Common! Executor framework, etc.
• Is it Command pattern if you run the command repeatedly?
If it takes an argument? Returns a val? GoF are vague on this.

17-214 35
Command Illustration

public static void main(String[] args) {


SwingUtilities.invokeLater(() -> new Demo().setVisible(true));
}

17-214 36
3. Interpreter

• Intent – given a language, define class hierarchy for parse tree,


recursive method(s) to interpret it
• Use case – regular expression matching
• Types – Expression, NonterminalExpression, TerminalExpression
• JDK – no exported uses I’m aware of
– Our cryptarithm expression evaluator (HW3) is a classic example
• Necessarily uses Composite pattern!

17-214 37
Interpreter Illustration

public interface Expression {


double eval(); // Returns value
String toString(); // Returns infix expression string
}

public class UnaryOperationExpression implements Expression {


public UnaryOperationExpression(
UnaryOperator operator, Expression operand);
}
public class BinaryOperationExpression implements Expression {
public BinaryOperationExpression(BinaryOperator operator,
Expression operand1, Expression operand2);
}
public class NumberExpression implements Expression {
public NumberExpression(double number);
}

17-214 38
4. Iterator

• Intent – provide a way to access elements of a collection without


exposing representation
• Use case – collections
• Types – Iterable, Iterator
– But GoF discuss internal iteration, too
• JDK – collections, for-each statement, etc.
• Note that the Iterator pattern uses the Factory Method pattern:
the iterator() method is a factory method

17-214 39
Iterator Illustration

Collection<String> c = ...;

for (String s : c) // Creates an Iterator appropriate to c


System.out.println(s);

17-214 40
5. Mediator

• Intent – define an object that encapsulates how a set of objects


interact, to reduce coupling.
– Instead of directly interacting with each other, objects interact indirectly
through a mediator
– 𝓞(n) couplings instead of 𝓞(n2)
• Use case – dialog box where change in one component affects
behavior of others
• Types – Mediator, Components
• JDK – I’m sure there’s one hiding somewhere

17-214 41
Mediator Illustration

17-214 42
6. Memento

• Intent – without violating encapsulation, allow client to capture


an object’s state, and restore it later if desired
• Use case – undo stack for operations that aren’t easily undone,
e.g., line-art editor
• Key type – Memento (opaque state object)
• JDK – none that I’m aware of (not serialization)

17-214 43
7. Observer

• Intent – let objects observe the behavior of other objects so they


can stay in sync with minimal coupling
• Use case – multiple views of a data object in a GUI
• Types – Subject, Observer (AKA event handler, AKA listener)
– GoF are agnostic on many details!
• JDK – Swing, left and right

17-214 44
Observer Illustration

// Implement roll button and dice type field


JTextField diceSpecField = new JTextField(diceSpec, 5); // Field width
JButton rollButton = new JButton("Roll");
rollButton.addActionListener(event -> {
if (!diceSpecField.getText().equals(diceSpec)) {
diceSpec = diceSpecField.getText();
dice = Die.dice(diceSpec);
jDice.resetDice(dice);
}
for (Die d : dice)
d.roll();
jDice.repaint();
});

17-214 45
8. State

• Intent – allow an object to alter its behavior when internal state


changes. “Object will appear to change class.”
• Use case – TCP Connection (which is stateful)
• Key type – State (Object delegates to state!)
• JDK – none that I’m aware of, but…
– Works great in Java
– Use enums as states
– Use AtomicReference<State> to store it (if you need thread-safety);
resulting state machine is highly concurrent.

17-214 46
9. Strategy

• Intent – represent a behavior that parameterizes an algorithm


for behavior or performance
• Use case – line-breaking for text compositing
• Types – Strategy
• JDK – Comparator

17-214 47
Strategy Illustration

Comparator is a strategy for ordering


public static synchronized void main(String[] args) {
Arrays.sort(args, reverseOrder());
System.out.println(Arrays.toString(args));

Arrays.sort(args, comparingInt(String::length));
System.out.println(Arrays.toString(args));
}

java Test i eat wondrous spam


[wondrous, spam, i, eat]
[i, eat, spam, wondrous]

17-214 48
10. Template Method

• Intent – define skeleton of an algorithm or data structure,


deferring some decisions to subclasses
• Use case – application framework that lets plugins implement all
operations on documents
• Types – AbstractClass, ConcreteClass
• JDK – skeletal collection implementations (e.g., AbstractList)

17-214 49
Template Method Illustration

// List adapter for primitive int arrays


public static List<Integer> intArrayList(final int[] a) {
return new AbstractList<Integer>() {
public Integer get(int i) {
return a[i];
}

public Integer set(int i, Integer val) {


Integer oldVal = a[i];
a[i] = val;
return oldVal;
}

public int size() {


return a.length;
}
};
}

17-214 50
11. Visitor
Probably the trickiest GoF pattern

• Intent – represent an operation to be performed on a recursive


object structure (e.g., a parse tree). This pattern lets you add
new operations on a tree without adding a method to the types
used to represent the tree.
• Use case – type-checking, pretty-printing, etc.
• Types – Visitor, ConcreteVisitors, all element types that get visited
• JDK – none that I’m aware of (but pattern is important)

17-214 51
Visitor Illustration (1/3: machinery)

public interface Expression {


public <T> T accept(Visitor<T> v); // No eval or toString!
}
public interface Visitor<T> { // T is result type
public T visitUnaryExpr(Unary Expression expr);
public T visitBinaryExpr(BinaryExpression expr);
public T visitNumberExpr(NumberExpression expr);
}
public class UnaryOperationExpression implements Expression {
public final UnaryOperator operator; public final Expression operand;
public <T> T accept(Visitor<T> v) { return v.visitUnaryExpr(this); }
}
public class BinaryOperationExpression implements Expression {
public final BinaryOperator operator; public final Expression op1, op2;
public <T> T accept(Visitor<T> v) { return v.visitBinaryExpr(this) ; }
}
public class NumberExpression implements Expression {
public final double val;
public <T> T accept(Visitor<T> v) { return v.visitNumberExpr(this); }
}

17-214 52
Visitor Illustration (2/3, eval visitor)

public class EvalVisitor implements Visitor<Double> {


public Double visitUnaryExpr(UnaryExpression ue) {
return ue.operator.apply(ue.operand.accept(this));
}

public Double visitBinaryExpr(BinaryExpression be) {


return be.operator.apply(be.op1.accept(this),
be.op2.accept(this));
}

public Double visitNumberExpr(NumberExpression ne) { return ne.val; }


}

17-214 53
Visitor Illustration (3/3, toString visitor)

public class ToStringVisitor implements Visitor<String> {


public String visitUnaryExpr(UnaryExpression ue) {
return ue.operator + ue.operand.accept(this);
}
public String visitBinaryExpr(BinaryExpression be) {
return String.format("(%s %s %s)", be.operand1.accept(this),
be.operator, be.operand2.accept(this));
}
public String visitNumberExpr(NumberExpression ne) {
return Double.toString(ne.number);
}
}

// Sample use of visitors


System.out.println(e.accept(new ToStringVisitor()) + " = " +
e.accept(new EvalVisitor()));

17-214 54
More on Visitor

• Visitor is NOT merely traversing a graph and applying a method


– That’s Iterator!
– Knowing this can prevent you from flunking a job interview 😉
• The essence of Visitor is double-dispatch of vist method
– First (dynamically) dispatch on the node type (visitee)
– Then dispatch on the operation (visitor)
– This gives you the flexibility to add a new operation to the tree without
adding a method to the node types

17-214 55
Summary

• Now you know all the Gang of Four patterns


• Definitions can be vague
• Coverage is incomplete
• But they’re extremely valuable
– They gave us a vocabulary
– And a way of thinking about software
• Look for patterns as you read and write software
– GoF, non-GoF, and undiscovered

17-214 56

You might also like