Design Patterns: Presented by Sangeeta Mehta EECS810 University of Kansas OCTOBER 2008
Design Patterns: Presented by Sangeeta Mehta EECS810 University of Kansas OCTOBER 2008
EECS810
UNIVERSITY OF KANSAS
OCTOBER 2008
Contents
2
Introduction to OO concepts
Introduction to Design Patterns
What are Design Patterns?
Why use Design Patterns?
Elements of a Design Pattern
Design Patterns Classification
Pros/Cons of Design Patterns
Popular Design Patterns
Conclusion
References
Good Design
Maintainability
Extensibility
Scalability
Testability
Reusablilty
Design Patterns
Singleton
Abstract Factory
DAO
Strategy
Decorator
Design Principles
Program to an interface, not an implementation
High cohesion
Low coupling
Open-Closed
Separation of concerns
Design Objectives
Good Design (the “ilities”)
High readability and maintainability
High extensibility
High scalability
High testability
High reusability
Solution
Describes elements, relationships, responsibilities, and
collaborations which make up the design
Consequences
Results of applying the pattern
Benefits and Costs
Subjective depending on concrete scenarios
Pros
Add consistency to designs by solving similar problems the same
way, independent of language
Add clarity to design and design communication by enabling a
common vocabulary
Improve time to solution by providing templates which serve as
foundations for good design
Improve reuse through composition
Cons
Some patterns come with negative consequences (i.e. object
proliferation, performance hits, additional layers)
Consequences are subjective depending on concrete scenarios
Patterns are subject to different interpretations, misinterpretations,
and philosophies
Patterns can be overused and abused Anti-Patterns
Observer
Singleton
Decorator
Proxy
Façade
Adapter
Identify the aspects of your application that vary and separate them
from what stays the same
Program to an interface, not an implementation
Favor composition over inheritance
Context «interface»
-strategy Strategy
- strategy: Strategy
+ algorithmInterface() : void
+ Context(Strategy)
+ contextInterface() : void
Cla ss1
Duck
+ display() : void
+ quack() : void
Cla ss1
«interface»
StrategyExample Duck QuackBehavior
setQuack
- quackBehavior: QuackBehavior + quack() : void
+ main() : void
{ performQuack + display() : void
//Instantiate a new MallardDuck + performQuack() : void
//Set its quack behavior to a new {
instance of Quack quackBehavior.quack();
//Invoke its performQuack() method } Quack Squeak
} + setQuackBehavior(QuackBehavior) : void MuteQuack
{ + quack() : void + quack() : void
{ + quack() : void
//Set the quackBehavior {
//Implements duck {
} //implements
quacking //do nothing - can't
duckie squeak quack!
} } }
Pros
Provides encapsulation
Hides implementation
Allows behavior change at runtime
Cons
Results in complex, hard to understand code if overused
Identify the aspects of your application that vary and separate them
from what stays the same
Program to an interface, not an implementation
Favor composition over inheritance
Strive for loosely coupled designs between objects that interact
class Observ er
«interface» «interface»
Subject Observer
observers
+ notifyObservers() : void + update() : void
+ registerObservers() : void
+ removeObservers() : void
ConcreteSubject ConcreteObserver
+ notifyObservers() : void subject + update() : void
+ registerObservers() : void
+ removeObservers() : void
WeatherData
update CurrentConditionsDiplay
- currentConditionsDisplay: CurrentConditionsDisplay
- humidity: float + update(float, float, float) : void
- pressure: float
- statisticsDisplay: StatisticsDisplay
- temp: float
+ getHumidity() : float update
+ getPressure() : float StatisticsDisplay
+ getTemperature() : float
+ update(float, float, float) : void
+ measurementsChanges() : void
(
//Get the changed float values
//Instantiate CurrentConditionsDisplay
//Call its update method with the float values
//Instantiate StatisticsDisplay
//Call its update method with the float values
}
«interface» «interface»
observers Observer
Subject
+ notifyObservers() : void + update(float, float, float) : void
+ registerObserver(Observer) : void
+ removeObserver(Observer) : void
WeatherData
CurrentConditionsDisplay StatisticsDisplay
- observers: ArrayList
+ CurrentConditionsDisplay(Subject) : void + StatisticsDisplay(Subject) : void
+ measurementsChanged() : void { {
{ //Store reference to WeatherData //Store reference to WeatherData
notifyObservers(); //Call WeatherData's registerObserver //Call WeatherData's registerObserver
} method to register self method to register self
+ notifyObservers() : void } }
{ subject
//sends the update message to each observer + update(float, float, float) : void + update(float, float, float) : void
in the observers list { {
} //get the new float values and display //get the new float values and display
+ registerObserver(Observer) : void accordingly accordingly
{ } }
//Adds the observer to the observers list
}
+ removeObserver(Observer) : void
{
//First locates the observer in the observers
list
//If found, removes it from the list
}
+ setMeasurements(float, float, float) : void
{
//Sets all the 3 measurements
}
Observer
24
Pros
Abstracts coupling between Subject and Observer
Supports broadcast communication
Supports unexpected updates
Enables reusability of subjects and observers independently of each
other
Cons
Exposes the Observer to the Subject (with push)
Exposes the Subject to the Observer (with pull)
Singleton
- instance: Singleton
+ getInstance() : Singleton
- Singleton() : void
if (instance == null)
{
instance = new Singleton();
}
class Singleton
BusinessDateChecker
BusinessObject
- CHRISTMAS: String = "12/25/08"
+ isBusinessday(Date) : boolean - INDEPENDENCE: String = "7/04/08"
{ - NEW_YEARS: String = "1/01/08"
uses
//Create a new instance of BusinessDateChecker
//Call BusinessDateChecker's isValidBusinessDate method + isValidBusinessDate(Date) : boolean
//Return the result {
} //Has knowledge about the various holidays
//Checks to see if the passed date is a holiday or a
weekend.
//Returns the appropriate result
}
Singleton - Solution
class Singleton
BusinessDateChecker
BusinessObject
- CHRISTMAS: String = "12/25/08"
+ isBusinessday(Date) : boolean - INDEPENDENCE: String = "7/04/08"
{ - NEW_YEARS: String = "1/01/08"
uses
//Create a new instance of BusinessDateChecker
- BusinessDateChecker() : void
//Call BusinessDateChecker's isValidBusinessDate method
{
//Return the result
} //Do nothing
}
+ getInstance() : BusinessDateChecker
{
if (instance == null)
{
instance = new BusinessDateChecker();
}
return instance;
}
+ isValidBusinessDate(Date) : boolean
{
//Has knowledge about the various holidays
//Checks to see if the passed date is a holiday or a
weekend.
//Returns the appropriate result
}
Singleton
29
cmp Proxy
return instance;
}
Pros
Increases performance
Prevents memory wastage
Increases global data sharing
Cons
Results in multithreading issues
University of
University of Kansas
Kansas 10/19/21
Patterns & Definitions – Group 1
32
University of
University of Kansas
Kansas 10/19/21
Patterns & Definitions – Group 1
33
University of
University of Kansas
Kansas 10/19/21
Patterns & Definitions – Group 1
34
University of
University of Kansas
Kansas 10/19/21
Decorator Definition
35
Identify the aspects of your application that vary and separate them
from what stays the same
Program to an interface, not an implementation
Favor composition over inheritance
Strive for loosely coupled designs between objects that interact
Classes should be open for extension, but closed for modification
Component
+ methodA() : void
+ methodB() : void
ConcreteComponent Decorator
+ methodA() : void + methodA() : void
+ methodB() : void + methodB() : void
ConcreteDecoratorA ConcreteDecoratorB
- wrappedObj: Component - wrappedObj: Component
+ methodA() : void + methodA() : void
+ methodB() : void + methodB() : void
+ newBehavior() : void
Decorator - Problem
38
class Decorator
Bev e rage
- descriptio n: String
- milk: boolean
- soy: boolean
- whip: boolean
+ cost() : double
{
//Add all the condiment's costs to the beverage cost
//The boolean methods help in determining if the
condiments
//have been added to the beverage.
//return the total cost
}
+ getDescriptio n() : String
+ hasMilk() : boolean
+ hasSoy() : boolean
+ hasWhip() : boolean
+ setMilk(boolean) : void
+ setSoy(boolean) : void
+ setWhip(boolean) : void
DarkRoast
Espr esso
+ cost() : double
{ + cost() : double
return 1.99 + super.cost() {
//return the beverage's cost and add it to the result of calling return 2.10 + super.cost();
//the superclass, Beverage's cost }
} + Espresso() : void
+ DarkRoast () : void {
{ description = "Very fine Espresso"
description = "Most Excellent Dark Roast" }
}
Beverage
- description: String = "Unknown Beverage"
+ cost() : double
{
//An abstract method. Implemented in the subclasses.
}
+ getDescription() : String
{
return description;
}
Mocha Milk
- beverage: Beverage - beverage: Beverage
+ cost() : double + cost() : double
{ + getDescription() : String
//Adds the cost of the condiment to the cost of
the decorated beverage
return .20 + beverage.cost();
}
+ getDescription() : String
{
//Attaches the name of the condiment to the
beverage name
return beverage.getDescription + ", Mocha";
}
+ Mocha(Beverage) : void
{
//Stores a reference to the Beverage in
consideration.
this.beverage = beverage;
}
Pros
Extends class functionality at runtime
Helps in building flexible systems
Works great if coded against the abstract component type
Cons
Results in problems if there is code that relies on the concrete
component’s type
class Proxy
Subject
Client
+ Request() : void
RealSubject Proxy
+ Request() : void + Request() : void
realSubject.Request()
NoProxyExample «interface»
Image
+ main() : void
{ uses + displayImage() : void
//Instantiate the image object
//Instantiating it loads the image
too.
//Display the image
}
RealImage
- filename: String
+ displayImage() : void
{
//Display the image
}
- loadImageFromDisk() : void
{
//Potentially expensive operation
}
+ RealImage(String) : void
{
this.filename = filename;
loadImageFromDisk();
}
«interface» ProxyExample
Image
+ main() : void
+ displayImage() : void
{
//Instantiates the ProxyImage
//Invokes the displayImage
method of ProxyImage
displayImage
RealImage ProxyImage
- filename: String - filename: String
- image: Image
+ displayImage() : void
{ + displayImage() : void
//Display the image {
} //Only if image is not already loaded, instantiate it.
- loadImageFromDisk() : void //Saves the expensive loading time.
{ if (image == null)
//Potentially expensive operation image = new RealImage (filename);
} image.displayImage();
+ RealImage(String) : void }
{ + ProxyImage(String) : void
this.filename = filename;
loadImageFromDisk();
}
Proxy
45
Pros
Prevents memory wastage
Creates expensive objects on demand
Cons
Adds complexity when trying to ensure freshness
Identify the aspects of your application that vary and separate them
from what stays the same
Program to an interface, not an implementation
Favor composition over inheritance
Strive for loosely coupled designs between objects that interact
Classes should be open for extension, but closed for modification
Principle of least knowledge – talk only to your immediate friends
class Facade
Client Facade
+ doSomething() : void doSomething + doSomething() : void
{ {
//Instantiate Facade //Instantiate Class1
//Do something //Instantiate Class2
} //do Class1's stuff
//do Class2's stuff
}
Class2 Classs1
+ doStuff() : void + doStuff() : void
{ {
//Do stuff //Do stuff
} }
class Facade
HardDrive
+ read(long, byte[]) : byte[]
uses
NonFacadeExample
CPU
+ main() : void
{ + execute() : void
//Instantiate the HardDrive object uses + freeze() : void
//Instanitate the CPU object + jump() : void
//Instantiate the Memory object
//Call the CPU's freeze method
//Call the Memory's load method uses
//Call the CPU's jump method
//Call the CPU's execute method Memory
} + load(long, byte[]) : void
class Facade
FacadeExample Computer
+ main() : void + startComputer() : void
{ {
//Instantiate the Computer facade object startComputer //Instantiate the HardDrive object
//Call the Computer's startComputer method //Instanitate the CPU object
} //Instantiate the Memory object
//Call the CPU's freeze method
//Call the Memory's load method
//Call the CPU's jump method
//Call the CPU's execute method
}
Pros
Makes code easier to use and understand
Reduces dependencies on classes
Decouples a client from a complex system
Cons
Results in more rework for improperly designed Façade class
Increases complexity and decreases runtime performance for large
number of Façade classes
class Adapter
«interface»
only sees the target
interface Target
Client + request() : void
class Adapter
SquarePeg
insert - successful
NoAdapterExample + insert(String) : void
{
+ main() : void //Insert string
{ }
//Instantiates a SquarePeg
//Calls SquarePeg's insert() method - Successful
//Instantiate a RoundPeg RoundPeg
//Only has knowledge of the insert() method of pegs
//The RoundPeg only implements insertIntoHole() insert - unsuccessful + insertIntoHole(String) : void
//It does not implement insert() {
//Call to insert() method on RoundPeg results in error //Insert string
} }
SquarePeg
insert - successful
AdapterExample + insert(String) : void
{
+ main() : void //Insert string
{ }
//Instantiates a SquarePeg
//Calls SquarePeg's insert() method - Successful
//Instantiate a new PegAdapter object
//Pass it the RoundPeg object reference PegAdapter
//Invoke the PegAdapter's insert() method
//Indirectly the RoundPeg object's insertIntoHole() - roundPeg: RoundPeg
method gets invoked insert - successful
} + insert(String) : void
{
//Invoke the roundPeg's
insertIntoHole() method
}
+ PegAdapter(RoundPeg) : void
{
//Set the roundPeg reference
to RoundPeg object
}
RoundPeg
+ insertIntoHole(String) : void
{
//Insert string
}
Adapter
56
Pros
Increases code reuse
Encapsulates the interface change
Handles legacy code
Cons
Increases complexity for large number of changes
University of
University of Kansas
Kansas 10/19/21
Patterns & Definitions – Group 2
58
Decorator Simplifies the interface of
Proxy a set of classes
Façade Wraps an object and
Adapter provides an interface to it
Wraps an object to
provide new behavior
Wraps an object to control
access to it
University of
University of Kansas
Kansas 10/19/21
Patterns & Definitions – Group 2
59
Decorator Simplifies the interface of
Proxy a set of classes
Façade Wraps an object and
Adapter provides an interface to it
Wraps an object to
provide new behavior
Wraps an object to control
access to it
University of
University of Kansas
Kansas 10/19/21
Patterns & Definitions – Group 2
60
Decorator Simplifies the interface of
Proxy a set of classes
Façade Wraps an object and
Adapter provides an interface to it
Wraps an object to
provide new behavior
Wraps an object to control
access to it
University of
University of Kansas
Kansas 10/19/21
Patterns & Definitions – Group 2
61
Decorator Simplifies the interface of
Proxy a set of classes
Façade Wraps an object and
Adapter provides an interface to it
Wraps an object to
provide new behavior
Wraps an object to control
access to it
University of
University of Kansas
Kansas 10/19/21
Pattern Classification
62
Strategy
Observer
Singleton
Decorator
Proxy
Façade
Adapter
University of
University of Kansas
Kansas 10/19/21
Pattern Classification
63
Strategy Behavioral
Observer
Singleton
Decorator
Proxy
Façade
Adapter
University of
University of Kansas
Kansas 10/19/21
Pattern Classification
64
Strategy Behavioral
Observer Behavioral
Singleton
Decorator
Proxy
Façade
Adapter
University of
University of Kansas
Kansas 10/19/21
Pattern Classification
65
Strategy Behavioral
Observer Behavioral
Singleton Creational
Decorator
Proxy
Façade
Adapter
University of
University of Kansas
Kansas 10/19/21
Pattern Classification
66
Strategy Behavioral
Observer Behavioral
Singleton Creational
Decorator Structural
Proxy
Façade
Adapter
University of
University of Kansas
Kansas 10/19/21
Pattern Classification
67
Strategy Behavioral
Observer Behavioral
Singleton Creational
Decorator Structural
Proxy Structural
Façade
Adapter
University of
University of Kansas
Kansas 10/19/21
Pattern Classification
68
Strategy Behavioral
Observer Behavioral
Singleton Creational
Decorator Structural
Proxy Structural
Façade Structural
Adapter
University of
University of Kansas
Kansas 10/19/21
Pattern Classification
69
Strategy Behavioral
Observer Behavioral
Singleton Creational
Decorator Structural
Proxy Structural
Façade Structural
Adapter Structural
University of
University of Kansas
Kansas 10/19/21
Conclusion - Design Principles
70
Identify the aspects of your application that vary and separate them
from what stays the same
Program to an interface, not an implementation
Favor composition over inheritance
Strive for loosely coupled designs between objects that interact
Classes should be open for extension, but closed for modification
Principle of least knowledge – talk only to your immediate friends
Good Design
Maintainability
Extensibility
Scalability
Testability
Reusablilty
Design Patterns
Singleton
Abstract Factory
DAO
Strategy
Decorator
Design Principles
Program to an interface, not an implementation
High cohesion
Low coupling
Open-Closed
Separation of concerns
http://en.wikipedia.org/wiki/Observer_pattern
http://en.wikipedia.org/wiki/Strategy_pattern
http://en.wikipedia.org/wiki/Decorator_pattern
http://en.wikipedia.org/wiki/Design_Patterns
http://en.wikipedia.org/wiki/Anti-pattern
http://en.wikipedia.org/wiki/Open/closed_principle
http://c2.com/ppr/wiki/JavaIdioms/JavaIdioms.html