DESIGN PATTERNS
Factory, Abstract Factory, Singleton and Adapter
Dr Simon Spacey
B.Sc. Hons. (York), M.Sc. (Lancaster), M.B.A. (Cass), J.L.P. (Keio),
D.E.A. (Montpellier), D.CSC. (Cambridge), D.I.U. (Imperial), Ph.D. (Imperial)
© Simon Spacey.
20/05/2013
<1>
What are Design Patterns?
¡ Design Patterns:
¡ Are Ways to Solve OOL Implementation Problems...
¡ ... that often have Trivially Obvious “Imperative” Solutions
¡ Popularised by the 1995 Book by Erich Gamma et al.
¡ Are often Supported by Libraries in OOLs
¡ Design Patterns Include:
¡ Creational:
Factory, Abstract Factory, Builder
Prototype, Singleton
¡ Structural:
Adapter (DAO), Bridge, Composite,
Decorator, Façade, Flyweight, Proxy
E. Gamma, R. Helm, R. Johnson, J.
Vlissides, Design Patterns, Addison
Wesley, 1995
¡ Behavioural: Chain of Responsibility, Command, Interpreter, Iterator, Mediator,
Memento, Observer (MVC), State, Strategy, Template, Visitor
© Simon Spacey.
18/04/2013
<2>
Factory Method: Overview
¡ The Factory Design Pattern Uses Overridable Factory Methods to Allow Code
to Instantiate Different Subclasses:
i.e can implement runtime
¡ Reducing the Need to Embed a Variety of Concrete Classes!
“Dependency Injection”
¡ Notes:
¡ A Factory Method can be Parameterised to Return Different Subclass Instances
¡ Factory Methods can be Used Internally in the Same a Class or in Abstract Factories
¡ Positives and Negatives:
ü Isolates Concrete Class Names from Usages (Clients)!
ü Makes Exchanging Classes Easier
ü Promotes Consistency (Subclasses can have Factories for Related Classes)
✘ Subclass Specific Operations May Require Runtime Dependent Casting
Spacey.
¡ © Simon
!
18/04/2013
<3>
Factory Method: UML
GameEngine
GameEngine
Pill
#newPill()
: Pill : Pill
#newPill()
+initialise()
+initialise()
Called by the
Internal Method
initialise()
#newPill()
: Pill : Pill
#newPill()
A UML
note
Pill3 Pill3
GameEngine3
GameEngine3 GameEngine4
GameEngine4
#newPill()
: Pill : Pill
#newPill()
+newInstance()
: Pill : Pill
+newInstance()
GameEngine2
Pill1 Pill1
GameEngine2
returnreturn
new Pill2(x,
y); y);
new Pill2(x,
#newPill()
:
Pill
+newInstance()
: Pill : Pill
#newPill() : Pill
+newInstance()
GameEngine1
GameEngine1
#newPill()
: Pill : Pill
#newPill()
returnreturn
new Pill4(x,
y); y);
new Pill4(x,
An Example UML Diagram for the
Internal Factory Method Design Pattern
© Simon Spacey.
18/04/2013
<4>
Pill
Pill2 Pill2
returnreturn
new Pill2(x,
y); y);
new Pill2(x,
+newInstance()
:
Pill
+newInstance() : Pill
Pill4 Pill4
+newInstance()
: Pill : +newInstance()
: Pill : Pill
+newInstance()
Pill +newInstance()
returnreturn
new Pill4(x,
y); y);
new Pill4(x,
An Example UML Diagram of the
External Factory Method Design Pattern
Factory Method: Internal Example
¡ Before:
¡ After:
!
!
...!
...!
!
!
!
// Class specialized so newPill() returns correct type!
protected Pill newPill(int x, int y) {!
return new Pill1(x, y);!
}!
"!
// Initialises the Pacman Pills, Power Pills and Ghosts!
public void initialise() {!
!
!
!
!
// Initialises the Pacman Pills, Power Pills and Ghosts!
public void initialise() {!
!
int style_id = 1;
!
!
!
!
...!
Switch(style_id) {!
case 1: displayList.add(new
case 2: displayList.add(new
case 3: displayList.add(new
case 4: displayList.add(new
}!
...!
!
...!
Pill1(x,
Pill2(x,
Pill3(x,
Pill4(x,
y));
y));
y));
y));
break;!
break;!
break;!
break;!
!
displayList.add(newPill(x, y)); // internal factory!
!
!
...!
!
}!
}!
!
...!
!
...!
!
18/04/2013
Would be the same
method inherited
by each subclass
!
!
© Simon Spacey.
Can lead to Many
Subclasses Each with
a Small Change
<5>
Factory Method: External Example
¡ Before:
¡ After:
!
!
...!
...!
!
!
!
!
!
!
"!
// Initialises the Pacman Pills, Power Pills and Ghosts!
public void initialise() {!
Change Hard Coded
Class Names in One
Place
!
"!
// Initialises the Pacman Pills, Power Pills and Ghosts!
public void initialise() {!
!
int style_id = 1;
!
!
...!
Switch(style_id) {!
case 1: displayList.add(new
case 2: displayList.add(new
case 3: displayList.add(new
case 4: displayList.add(new
}!
...!
Pill pill = new Pill1(); // factory in external class!
!
...!
!
Pill1(x,
Pill2(x,
Pill3(x,
Pill4(x,
y));
y));
y));
y));
!
break;!
break;!
break;!
break;!
displayList.add(pill.newInstance(x, y));!
!
!
...!
!
}!
!
!
}!
!
...!
© Simon Spacey.
...!
!
18/04/2013
<6>
Rest of the
code is generic
Abstract Factory: Overview
¡ The Abstract Factory Design Pattern Provides an Abstract Interface for
Instantiating Related Classes:
¡ Further Reducing the Need to Embed Concrete Classes!
¡ Notes:
¡ The Abstract Factory Base may be an Interface or Defaulted
¡ Positives and Negatives:
ü Isolates Concrete Class Names from Usages (Clients)!
ü Makes Exchanging Product Families Easy (Single Usage)
ü Promotes Consistency (Products from Same Factory)
✘ Supporting new Products Means a New Interface
✘ Subclass Specific Operations May Require Runtime Dependent Casting
© Simon Spacey.
18/04/2013
<7>
Abstract Factory: UML
Interface,
Abstract Class or
Insatiable Default
Parent
Style
+newPill() : Pill
+newPowerPill() : PowerPill
+newGhost() : Ghost
+newCherry() : Cherry
Concrete Subclass/
Specialism with
Factory Methods
Style1
Style2
+newPill() : Pill
+newPowerPill() : PowerPill
+newGhost() : Ghost
+newCherry() : Cherry
+newPill() : Pill
+newPowerPill() : PowerPill
+newGhost() : Ghost
+newCherry() : Cherry
GameEngine3
Style3
return new Pill2(x, y);
Style4
return new Pill4(x, y);
+newPill()
#newPill()
: Pill: Pill
+newPowerPill() : PowerPill
+newGhost() : Ghost
+newCherry() : Cherry
+newPill() : Pill
+newPowerPill() : PowerPill
+newGhost() : Ghost
+newCherry() : Cherry
An Example UML Diagram for the Abstract Factory Design Pattern
© Simon Spacey.
18/04/2013
<8>
Abstract Factory: Example
¡ Before:
¡ After:
!
!
!
...!
...!
"!
// Initialises the Pacman Pills, Power Pills and Ghosts!
public void initialise(int style_id) {!
!
...!
switch(style_id) {!
case 1: displayList.add(new Pill1(x, y)); break;!
case 2: displayList.add(new Pill2(x, y)); break;!
case 3: displayList.add(new Pill3(x, y)); break;!
case 4: displayList.add(new Pill4(x, y)); break;!
}!
...!
!
...!
switch(style_id) {!
case 1: displayList.add(new Ghost1(x, y)); break;!
case 2: displayList.add(new Ghost2(x, y)); break;!
case 3: displayList.add(new Ghost3(x, y)); break;!
case 4: displayList.add(new Ghost4(x, y)); break;!
}!
...!
}!
"!
// Initialises the Pacman Pills, Power Pills and Ghosts!
public void initialise(Style style) {!
!
...!
...!
© Simon Spacey.
!
!
displayList.add(style.newPill(x, y));!
!
!
!
...!
!
!
...!
!
!
displayList.add(style.newGhost(x, y));!
!
!
...!
}!
!
!
18/04/2013
<9>
...!
Singleton: Overview
¡ The Singleton Design Pattern Uses Static State to Ensure Only a Single
Instance of a Class Exists:
¡ Useful for creating a “global” state variable in OOP!
¡ Notes:
¡ A Single (Static) Instance is Returned by an Access Method
¡ Positives and Negatives:
ü Controlled Access to a Single Instance (e.g. could ensure single user at a time)!
ü Allows Class Namespace Encapsulation (c.f. C statics) rather than Global Instances
ü Allows an Instance Pool (can return 1 of many possible internal instances)
✘ Additional Mechanisms Required to Support Synchronization
✘ Have to call a Non-Standard Method Rather than Using the Standard Constructor
© Simon Spacey.
18/04/2013
<10>
Singleton: UML
Global
-style : Style
-score : unsigned int
-pills_left : unsigned int
-lives_left : unsigned int
+getStyle() : Style
+getScore() : unsigned int
+incScore() : unsigned int
+getPills() : unsigned int
+decPills() : unsigned int
+getLives() : unsigned int
+decLives() : unsigned int
Underlined means
“static” in UML
An Example UML Diagram for the Singleton Design Pattern
© Simon Spacey.
18/04/2013
<11>
Public Access
Methods return
Static Instances
Singleton: Example
¡ Before:
¡ After:
!
!
"!
public class Global {!
!
Initialising style to a single instance
on first Global class load in JVM to
prevent thread issues
!
!
private static Style style = new Style1();!
!
!
!
public static Style getStyle() {return style;}!
!
!
!
...!
!
}!
!
!
!
!
!
!
...!
...!
// Initialises the Pacman Pills, Power Pills and Ghosts!
public void initialise(Style style) {!
!
"!
// Initialises the Pacman Pills, Power Pills and Ghosts!
public void initialise() {!
!
Style style = Global.getStyle(); // note statics in defs!
!
!
!
!
...!
displayList.add(style.newPill(x, y));!
...!
displayList.add(style.newGhost(x, y));!
...!
!
}!
...!
displayList.add(style.newPill(x, y));!
...!
displayList.add(style.newGhost(x, y));!
...!
}!
!
...!
© Simon Spacey.
18/04/2013
<12>
...!
!
Adapter (DAO): Overview
¡ The Adapter Pattern Wraps One or More Classes with A Required Interface:
¡ Useful for Constructing say a standard Data Access Object (DAO) interface
¡ Notes:
¡ Can be an Abstract or a Concrete Class with Embedded “Composed-of” Relations
¡ Positives and Negatives:
ü Decouples Interface from Implementation
ü Client Code Stable if Wrapped Classes Changes (change Adapter Internally)
ü The Implementation and Adapter can be Subclassed Separately (//el Hierarchies)
ü Can Hide/ Share Implementations (e.g. Compiled Wrapper Libraries)
✘ Extra Layer of Programming Indirection (Code Complication)
© Simon Spacey.
18/04/2013
<13>
Adapter (DAO): UML
Static compositions
DAO
DriverManager
-c : Connection
-s : Statement
-r : ResultSet
1
+getHighScore() : unsigned int
+setHighScore()
0..1
+getConnection() : Connection
1
0..1
1
1
+createStatement() : Statement
0..1
Adapter Methods “Wrap”
Composed and
Associated Methods
An Associated Class
(but not composed)
Connection
Statement
+executeQuery() : ResultSet
0..1
ResultSet
+next() : bool
+getInt() : int
+getString() : String
An Example UML Diagram for the Adapter (DAO) Design Pattern
© Simon Spacey.
18/04/2013
<14>
Adapter (DAO): Example
¡ Before:
¡ After:
!
!
import java.sql.*;!
!
...!
!
import java.sql.*;!
!
...!
!
!
!
//*** Simple Adapter between JDBC and the Application!
public class DAO {!
!
!
!
private static Connection c = null;!
private static Statement s = null;!
private static RecordSet r = null;!
!
!
!
!
!
!
// Prints the High Score!
public void printHighScore() {!
Connection c = DriverManager.getConnection(!
"jdbc:mysql://localhost:3306/pacman",!
"packman", "password");!
Statement s = c.createStatement();!
ResultSet r = s.executeQuery(!
"SELECT MAX(score) FROM scores");!
unsigned int hc = (r.next() ? r.getInt(1) : 0);!
s.close(); c.close(); r.close();!
Console.out.println("High Score: " + hc);
}!
...!
© Simon Spacey.
18/04/2013
<15>
!
}!
Why
synchronized
if reading?
...!
public synchronized unsigned int getHighScore() {!
if(c == null) DAO.initialise();!
r
= s.executeQuery("SELECT MAX(score) FROM scores");!
return (r.next() ? r.getInt(1) : 0);!
}!
...!
!
!
...!
// Prints the High Score!
public void printHighScore() {!
Console.out.println("High Score: " + DAO.getHighScore());!
}!
...
Summary
¡ Design Patterns:
¡ Are Ways to Solve OOL Implementation Problems...
¡ ... that often have Trivially Obvious “Imperative” Solutions
¡ Popularised by the 1995 Book by Erich Gamma et al.
¡ Are often Supported by Libraries in OOLs
¡ Design Patterns Include the:
¡ Factory Method Pattern – Uses a Method to Construct Instances Instead of new!
¡ Abstract Factory Pattern – Provides an Interface with a Collection of Factory Methods
¡ Singleton Pattern
– Uses Static State to Ensure Only One Instance Exists
¡ Adapter (DAO) Pattern
– Wraps a Required Interface around One or More Classes
© Simon Spacey.
18/04/2013
<16>
© Copyright 2025