DESIGN PATTERNS Factory, Abstract Factory, Singleton and Adapter Dr Simon Spacey

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>