Title: Introduction to Design Pattern
1Introduction to Design Pattern
2Gang of Four Design Patterns
Behavioral patterns Chain of responsibility
Command Interpreter Iterator Mediator
Memento Observer State Strategy Template
method Visitor
Creational patterns Abstract factory Builder
Factory method Prototype Singleton
Structural patterns Adapter Bridge Composite
Decorator Facade Flyweight Proxy
3General Principles
- The Single-Responsibility Principle (SRP)
- The Interface-Segregation Principle (ISP)
- The Open-Closed Principle (OCP)
- The Liskov Substitution Principle (LSP)
4The Single-Responsibility Principle (SRP)
- A class should have only one reason to change
- Why?
- Every responsibility is an axis of change.
- The change will be manifest/cascade
5An Example of SRP Violation
Modem.java Interface Modem public void
dial(String pno) public void hangup() public
void send(char c) public char recv()
- Two responsibilities
- Connection management dial and hangup
- Communication management send and recv
6Refactoring
ltltinterfacegtgt Data Channel send(char) recv()
ltltinterfacegtgt Connection dial(pnoString) hangu
p()
Modem Implementation
7Another Example of SRP Violation
Employee calculatePay Store
Persistence Subsystem
8The Interface-Segregation Principle (ISP)
- It deals with fat interfaceInterface
Contamination. - Different client needs different services
Customized Service
9The Interface-Segregation Principle (ISP)
Client1
Client2
ltltinterfacegtgt Service1 m1() p2()
ltltinterfacegtgt Service2 m2() p1()
Service includes public function m1(),
m2(), p1(), p2()
Service
10An Example of ISP Violation
ltltinterfacegtgt BadExample first() void last()
void next() void previous() void getExcerpt()
String getFullRecord() String reIndexAll()
void updateIndex() void search(keywords
String) void getResult() void
Client -indexCursor Indexer -searcher Searcher
11Refactoring
Client -indexCursor Indexer -searcher Searcher
ltltinterfacegtgt Indexer reIndexAll()
void updateIndex() void
ltltinterfacegtgt Searcher search(keywords String)
void getResult() void
Interface cant be instantiated
ltltinterfacegtgt ResultSet first() void last()
void next() void previous() void getExcerpt()
String getFullRecord() String
FileIndexer reIndexAll() void updateIndex()
void
RdbIndexer reIndexAll() void updateIndex()
void
12The Open-Closed Principle (OCP)
- Software entities (classes, modules, functions,
etc) should be open to extension, but closed for
modification - Principle of Encapsulation of Variation (EVP)
- "Open For Extension" extend/change the behavior
of the module as the requirements change - "Closed For Modification" - Extending the
behavior of the module does not result in the
changing of the source code or binary code of the
module itself.
13An Example of OCP Violation
- Client is not open and closed
Server1
Client
Server2
14Refactoring
- STRATEGY pattern Client is both open and closed
(open to extension and closed for modification) - Abstraction is the key
Client
ltltinterfacegtgt Client Interface
Server
15The Liskov Substitution Principle (LSP)
- Subtypes must be substitutable for their base
types - Whenever a method accepts a base type, it must
accept the base types derived class. For
example - If method1(Base base),
- Then method1(Derived derived)
Base base
Tester method1(Base)
Derived derived
16Rectangle vs. Square
Rectangle.java public class Rectangle private
long width private long height public void
setWidth(long width) this.width width
public long getWidth() return this.width
public void setHeight(long height) this.height
height public long getHeight() return
this.height
Square.java public class Square private long
side public void setSide(long side) this.side
side public long getSide() return side
Rectangle width long height long
Square side int
17Rectangle vs. Square
public class Square extends Rectangle private
long side private long height public void
setWidth(long width) setSide(width) public
long getWidth() return getSide() public void
setHeight(long height) setSide(height)
public long getHeight() return getSide()
public long getSide() return side public
void setSide(long side) this.side side
Rectangle width long height long
Square width long height long side int
18Problem
Rectangle width long height long
Tester resize void
Tester.java public class Tester public void
resize(Rectangle r) while(r.getHeight() lt
r.getWidth() ) r.setWidth(r.getWidth() 1 )
Square width long height long side int
19Refactoring
ltltinterfacegtgt Quadrangle widthlong heightlong
Quardrangle.java public interface
Quardrangle public long getWidth() public long
getHeight()
Inheritance from abstraction, not from
implementation
Square sidelong widthlong heightlong
Ractangle widthlong heightlong
20Source code
Rectangle.java public class Rectangle
implements Quadrangle private long
width private long height public void
setWidth(long width) this.width width
public long getWidth() return this.width
public void setHeight(long height) this.height
height public long getHeight() return
this.height
Square.java public class Square implements
Quadrangle private long side public void
setSide(long side) this.side side public
long getSide() return side public long
getWidth() return getSide() public long
getHeight() return getSide()
21Factories
Creates
Creates
Simple Factory
Factory Pattern
Creates
Abstract Factory
Creates
22Simple Factory
ltltinterfacegtgt Fruit growvoid harvestvoid plan
tvoid
FruitGardener factoryFruit
Grape growvoid harvestvoid plantvoid seedl
essboolean
Apple growvoid harvestvoid plantvoid treeA
geboolean
Strawberry growvoid harvestvoid plantvoid
23Source Code
FruitGardener.java Public class
FruitGardener Public static Fruit factory(String
which) if(which.equalsIgnoreCase(apple))
return new Apple() if(which.equalsIgnoreCase(
strawberry)) return new Strawberry()
if(which.equalsIgnoreCase(grape)) return
new grape() else throw new Exception(no
such fruit)
24Factory
ltltinterfacegtgt Fruit growvoid harvestvoid plan
tvoid
ltltinterfacegtgt FruitGardener factory Fruit
Creates
AppleGardener factory Fruit
Strawberry Gardener factory Fruit
GrapeGardener factory Fruit
Apple growvoid harvestvoid plantvoid
Strawberry growvoid harvestvoid plantvoid
Grape growvoid harvestvoid plantvoid
25Sequence Diagram
Client.java Public class Client Private static
Fruit apple,grape Private static FruitGardener
aG, gG Public static void main(String
args) aG new AppleGardener() apple
aG.factory() gG new GrapeGardener() Grape
gG.factory()
Client
AppleGardener
new
Factory() Apple
Apple
new
26Abstract Factory
27 Garden Example
ltltinterfacegtgt Gardener
ltltinterfacegtgt Fruit
TropicalGardener createFruitFruit createVeggie
Veggie
TropicalFruit TropicalFruit nameString
NorthenGardener createFruitFruit createVeggieV
eggie
NorthernFruit NorthernFruit nameString
Creates
Creates
ltltinterfacegtgt Veggie
TropicalVeggie TropicalVeggie nameString
NorthernVeggie NorthernVeggie nameString
28Source Code1
Interface Gardener public interface Gardener
NorthernGardener.java public class
NorthernGardener implements Gardener public
Fruit createFruit(String name) return new
NorthernFruit(name) public Veggie
createVeggie(String name) return new
NorthernVeggie(name) TropicalGardener.java
public class TropicalGardener implement
Gardener public Fruit createFruit(String
name) return new TropicalFruit(name) public
Veggie createVeggie(String name) return new
TropicalVeggie(name)
29Source Code2
interface Fruit public interface Fruit
interface Veggie public interface Veggie
Northern Fruit.java public class
NorthernFruit(String name) private String
name public NorthernFruit(String
name) this.name name public String
getName() return name public void
setName(String name) this.name name
TropicalFruit.java public class
TropicalFruit(String name) private String
name public TropicalFruit(String
name) this.name name public String
getName() return name public void
setName(String name) this.name name
NorthernVeggie.java public class
NorthernVeggie(String name) private String
name public NorthernVeggie(String
name) this.name name public String
getName() return name public void
setName(String name) this.name name
TropicalVeggie.java public class
TropicalVeggie(String name) private String
name public TropicalVeggie(String
name) this.name name public String
getName() return name public void
setName(String name) this.name name
30Another Example
ltltinterfacegtgt Button paintvoid
ltltinterfacegtgt GUIFactory createButtonvoid
WinButton
OSXButton
WinFactory createButton Void createMenu Void
OSXFactory createButton Void createMenu Void
Creates
ltltinterfacegtgt Menu
Creates
WinMenu
OSXMenu
31Source Code
class WinButton extends Button public void
paint() System.out.println("I'm a
WinButton caption) class OSXButton
extends Button public void paint()
System.out.println("I'm a OSXButton
caption) public class Application
public static void main(String args)
GUIFactory aFactory GUIFactory.getFactory()
Button aButton aFactory.createButton() Menu
aMenu aFactory.createMenu() aButton.setCaption(
"Play Button") aButton.paint()
aMenu.setCaption("Play Menu") aMenu.paint()
//output is I'm a WinButton Play Button I'm
a WinMenu Play Menu OR I'm a
OSXButton Play Button I'm a OSXMenu Play Menu
/ GUIFactory example / public abstract class
GUIFactory public static GUIFactory
getFactory() int sys readFromConfigFile("
OS_TYPE") if (sys 0) return(new
WinFactory()) else return(new
OSXFactory()) public abstract Button
createButton() class WinFactory extends
GUIFactory public Button createButton()
return(new WinButton()) class
OSXFactory extends GUIFactory public
Button createButton() return(new
OSXButton()) public abstract class Button
private String caption public
abstract void paint() public String
getCaption() return caption
public void setCaption(String caption)
this.caption caption
32Composite Design Pattern
- This pattern allows a client object to treat both
single components and collections of
components identically - file system
- recursive
- AWT SWING
- Bi-direction, leaf holds reference to composite
- Cache leaf to enhance performance
- Two variation transparent pattern and safe
pattern
33Safety Style Class Diagram
ltltinterfacegtgt Component defaultMethod()
Client aComponent Component
0..
Composite defaultMethod() getChild() addCompone
nt removeComponent
Leaf defaultMethod()
34Source Code
import java.util. interface Component
public String defaultMethod() public
ArrayListltComponentgt getChildren() public
boolean addComponent(Component c) public
boolean removeComponent(Component c)
class Leaf implements Component private String
id public Leaf(String identification) id
identification public String
defaultMethod() return id
class Composite implements Component private
String id private ArrayListltComponentgt
components new ArrayListltComponentgt() public
Composite(String identification) id
identification public String defaultMethod()
String s "(" id "" for
(Component child getChildren()) s s " "
child.defaultMethod() return s ")"
public ArrayListltComponentgt getChildren()
return components public boolean
addComponent(Component c) return
components.add(c) public boolean
removeComponent(Component c) return
components.remove(c)
class CompositePattern public static void
main(String args) Composite england new
Composite("England") Leaf york new
Leaf("York") Leaf london new Leaf("London")
england.addComponent(york) england.addComponent
(london) england.removeComponent(york)
Composite france new Composite("France")
france.addComponent(new Leaf("Paris"))
Composite europe new Composite("Europe")
europe.addComponent(england) europe.addComponen
t(france) System.out.println(
europe.defaultMethod() ) //output
(Europe (England London) (France Paris))
35Transparent Style Class Diagram
ltltinterfacegtgt Component defaultMethod() getChild
() addComponent removeComponent
Client aComponent Component
0..
class Leaf implements Component private String
id public Leaf(String identification) id
identification public String
defaultMethod() return id public
ArrayListltComponentgt getChildren() return
null public boolean addComponent(Component c)
return false public boolean
removeComponent(Component c) return false
Composite defaultMethod() getChild() addCompone
nt removeComponent
36Another Safety Style Example
Graphics drawvoid
Line drawvoid
Rectangle drawvoid
Circle drawvoid
Picture -listVector drawvoid addvoid remove
void getChildGraphics
37Source Code
abstract public class Graphics public
abstract void draw()
public class Line extends Graphics public
void draw() //code for drawing line
public class Picture extends Graphics private
VectorltGraphicsgt list list new
Vector(10) public void draw() for(int
i0iltlist.size()i) Graphics
glist.get(i) g.draw() public void
add(Graphics g) list.add(g) public void
remove(Graphics g) list.remove(g) public
Graphics getChild(int i) return list.get(i)
public class Rectangle extends Graphics
public void draw() //code for drawing
rectangle
public class Circle extends Graphics public
void draw() //code for drawing circle
38The Strategy Pattern
- Define a family of algorithms, encapsulate each
one, and make them interchangeable. It lets the
algorithm vary independently from clients that
use it. GOF - It embodies two principlesencapsulate the
concept that varies and program to an interface,
not an implementation. - loosely coupled collection of interchangeable
parts vs. monolithic, tightly coupled system - extensible, maintainable, and reusable
- if/else problem
- Strategy behavior/dynamic vs. Bridge static
39Class Diagram
40Pros and Cons
- Moving the common code from detailed strategy
class to its base abstract class - Hiding complex detail information from client
- Client decides to use which strategy dynamically
41Sort Sample
Sorter/Client sortvoid add(String)void setSor
tStrategy SortStrategy
SortStrategy sortvoid
BubbleSort sortvoid
HeapSort sortvoid
QuickSort sortvoid
42How to Invoke
static void Main( Sorter studentRecords new
Sorter()studentRecords.add("Samual")studentRec
ords.add("Jimmy")studentRecords.add("Sandra")
studentRecords.setSortStrategy(new
QuickSort())studentRecords.sort()studentRecord
s.SetSortStrategy(new HeapSort())studentRecords.
sort()
43Discount Sample
DiscountStrategy caclDiscountdouble
Client
NoDiscount -pricedouble -copiesint NoDiscount
caclDiscountdouble
FlatRate -pricedouble -copiesint NoDiscount c
aclDiscountdouble amountdouble
Percentage -pricedouble -copiesint NoDiscount
caclDiscountdouble percentdouble
44Source Code
public class Percentage extends DiscountStategy
private single percent private single price
0 private int copies 0 public Percentage
(single price, int copies) this.price
price this.copies copies public single
getPercentage() return percent public
void setPercentage(single percent)
this.percent percent public single
calcDiscount() return copiespricepercent
public abstract class DiscountStrategy private
single price 0 private int copies 0 public
abstract single calcDiscount() public
DiscountStrategy(single price, int copies)
this.price price this.copies copies
public class NoDiscount extends DiscountStategy
private single price 0 private int copies
0 public NoDiscount (single price, int
copies) this.price price this.copies
copies public single calcDiscount()
return 0
public class Client public static void
main(String args) DiscountStrategy anew
Percentage( 100,1000) a.setPercentage(0.1) d
ouble discounta.calcDiscount()
45If/Else Problem
public class Client private int copies private
double price private String discountType private
double amount private double percent public
double calcDiscount(String discountType, int
copies, double price) if(discountType.equals(N
oDiscount) return copiesprice else(
if(discountType.equals(FlatDiscount) return
copiesprice-amount else( if(discountType.equals
(PercentageDiscount)
46Decorator Design Pattern
- Wrapping the new "decorator" object around the
original object - typically by passing the original object as a
parameter to the constructor of the decorator,
with the decorator implementing the new
functionality. - the interface of the original object needs to be
maintained by the decorator. - Transparent vs. semi-transparent style
- Decorator adding new behavior at runtime vs.
subclassing adding new behavior at compile time
47Class Diagram
Concrete Component
Decorator
48Sequence Diagram
Original Class
49Java I/O Decorator
Reader read()
FileReader read()
BufferedReader read() readLine()
LineNumberReader read() readLine() getLineNumb
er()
50Sequence Diagram
51import java.io.BufferedReaderimport
java.io.FileReader import java.io.LineNumberRead
er public class Tester public static void
main(String args) read("c\\result.xml")
public static void read(String filename) try
FileReader frdr new FileReader(filename)
BufferedReader brdr new BufferedReader(frdr)
LineNumberReader lrdr new LineNumberReader(brdr
) //Reader rdr new LineNumberReader(brdr) f
or(String line (line lrdr.readLine()) !
null) //rdr.read() //read a single
character System.out.print(lrdr.getLineNumber()
"\t") printLine(line)
catch(java.io.FileNotFoundException fnfx)
fnfx.printStackTrace() catch(java.io.IOExcept
ion iox) iox.printStackTrace() private
static void printLine(String s) for(int c,
i0 i lt s.length() i) c s.charAt(i)
if(c '\t') System.out.print(" ") else
System.out.print((char)c) System.out.println(
)
52References
- Agile Software Development by Robert C. Martin
- Gang of Four Design Patterns
- Design Patterns by Yanhong
- http//www.tml.tkk.fi/pnr/GoF-models/html/
- http//en.wikipedia.org/wiki/ImageAbstract_factor
y_UML.svg - http//en.wikipedia.org/wiki/Composite_pattern
- http//en.wikipedia.org/wiki/Decorator_pattern
- http//www.javaworld.com/cgi-bin/mailto/x_java.cgi