0% found this document useful (0 votes)
48 views112 pages

Hands-On Design Patterns Slides

The document outlines a 2-day crash course on Design Patterns led by Nuno Flores, focusing on improving object-oriented design skills. It emphasizes the importance of understanding and applying design patterns to solve common programming problems while avoiding misconceptions. The course aims to provide practical insights into when and how to use design patterns effectively in software development.

Uploaded by

Pedro
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)
48 views112 pages

Hands-On Design Patterns Slides

The document outlines a 2-day crash course on Design Patterns led by Nuno Flores, focusing on improving object-oriented design skills. It emphasizes the importance of understanding and applying design patterns to solve common programming problems while avoiding misconceptions. The course aims to provide practical insights into when and how to use design patterns effectively in software development.

Uploaded by

Pedro
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/ 112

9/22/11

Hands-­‐On  Design  Patterns  


A  2-­‐Day  Crash  Course  

 Nuno  Flores  -­‐  FEUP  –  Software  Engineering  Group  

FEUP ● Nuno Flores ●


1

Setup  time…  
 Registering  and  signing  in…  
 Grouping?  
 Environment?  
 Notebooks?  
 All  set?  

FEUP ● Nuno Flores ●


2

1
9/22/11

Goals  
Before...
 

+ =
A problem... Your brain A solution

After...

+ + =
A problem... Your brain A better solution
Design Patterns
FEUP ● Nuno Flores ●
3

What  we’re  trying  (and  not)  


 To  make  you  all  Design  Patterns  experts?  
 To  try  to  improve  your  OO  design  skills?  
 To  make  you  use  Design  Patterns  all  the  time?  
 To  make  you  realise  you  are  probably  a  good  OO  Designer  
already?  
 To  bore  you  with  an  endless  theoretical  presentation?  
 To  make  you  see  Design  Patterns  may  help,  but  on  the  other  hand,  
may  not?  
 To  show  you  that  you  have  misconceptions  about  Design  
Patterns?  
 To  tell  you  what  Design  Patterns  are?  
 To  show  where  to  use  (or  not)  Design  Patterns?  
 To  challenge  you  on  using  Design  Patterns?  
 
FEUP ● Nuno Flores ●
4

2
9/22/11

OO  Basics  
 Object-­‐oriented  Design  
• Ok,  and  programming…eventually  

 Why  is  Object-­‐Oriented  a  pie?  


• A  bstraction  
• P  olimorphism  
• I  nheritance   OO
• E  ncapsulation   Basic
s!
Abstr
action
!
Encap
sulati
on!
Polym
orphis
Inheri m!
tance!

FEUP ● Nuno Flores ●


5

Welcome  to  Design  Patterns  


 Someone  has  already  solved  your  problems.  
 Best  way  to  use  patterns  
1. Load  your  brain  with  them  
2. Recognize  places  in  your  designs  and  existing  applications  where  
you  can  apply  them  
3. Instead  of  code  reuse,  you  get  experience  reuse.  

 Design  patterns  solve  problems…  


 …so  lets  get  right  to  some  problems…  

FEUP ● Nuno Flores ●


6

3
9/22/11

SimUDuck  
 Duck  pond  simulation  game  
• Showing  a  large  variety  of  duck  species  swimming  and  making  
quacking  sounds.  

Duck
quack()
swim()
display()
//OTHER duck-like methods

MallardDuck RedheadDuck
Other types of
display() { display() { ducks that inherit
// looks like a mallard } // looks like a redhead } from the Duck class

FEUP ● Nuno Flores ●


7

SimUDuck  
 But  now  we  need  ducks  to  fly…  

Duck
All subclasses quack()
inherit fly(). swim()
display()
fly()
//OTHER duck-like methods

MallardDuck RedheadDuck
Other types of
display() { display() { ducks that inherit
// looks like a mallard } // looks like a redhead } from the Duck class

FEUP ● Nuno Flores ●


8

4
9/22/11

SimUDuck  
 Rubber  ducks  flying!!!  Oooppss!!  

Duck
All subclasses
inherit fly(), quack()
including those swim()
who shoudn’t. display()
fly()
//OTHER duck-like methods

Rubber ducks don’t


quack, so quack() is
overridden to
“squeak”
MallardDuck RedheadDuck RubberDuck

display() { display() { quack() {


// looks like a mallard } // looks like a redhead } // overriden to squeak
}
display() {
// looks like a rubberduck
}

FEUP ● Nuno Flores ●


9

SimUDuck  
 What  happened?  
• Use  of  inheritance  
-­‐ Good  for  reuse.   RubberDuck
-­‐ Bad  for  maintenance.   quack() { // squeak}
display() { // rubberduck}
 Alternatives?   fly() {
// override to do
• Override  fly()  method.   nothing
}
 Other  consequences  
• What  if  we  want  to  add  wooden  decoy  ducks?  

DecoyDuck

quack() {
// override to do nothing
}
display() { // decoy duck}
fly() {
// override to do nothing
}
FEUP ● Nuno Flores ●
10

5
9/22/11

SimUDuck  
 How  about  an  interface?  
Duck
Quackable
swim()
quack()
Flyable display()
//OTHER duck-like methods
fly()

MallardDuck RedheadDuck RubberDuck DecoyDuck

display() display() display() display()


fly() fly() quack()
quack() quack()

FEUP ● Nuno Flores ●


11

SimUDuck  
 Can  you  say  “duplicate  code”?  
• What  if  we  need  to  change  the  flying  behaviour  (in  all  the  48  duck  
subclasses)?  

 So  what  now?  
• Inheritance  not  the  answer  
-­‐ Not  all  of  the  duck  subclasses  “fly”  ou  “quack”  
• Interfaces  destroys  code  reuse  
-­‐ Solves  rubber  ducks  flying…  
-­‐ But  creates  a  maintenance  nightmare.  

 Design  Patterns  to  the  rescue?  


• Not  just  yet…  
• Lets  figure  out  a  solution  the  old-­‐fashioned  way  
-­‐ Applying  good  OO  software  design  principles…  

FEUP ● Nuno Flores ●


12

6
9/22/11

Axiom  
 What  is  the  one  thing  you  can  always  count  on  in  software  
development?  
• Independent  of  the  programming  language…  
• Independent  of  the  problem  domain…  
• Independent  of  the  task  at  hand…  
• Independent  of  where  you  work…  

CHANGE
 No  matter  how  well  you  design  na  application,  over  time  an  
application  must  grow  and  change  or  it  will  die.  
 

FEUP ● Nuno Flores ●


13

Zeroing  in  on  the  problem…   cts


e aspe
d e n t ify th lication
I r app
 “Take  what  varies  and  “encapsulate”  it  so  it   of youary and m
th a t v m fro me.!
te the
won’t  affect  the  rest  of  the  code.”   separa tays the s
s
a
what
• Take  the  parts  that  vary  and  encapsulate  them,  so  
that  later  you  can  alter  or  extend  the  parts  that  vary  
without  affecting  those  that  don’t.  

 The  result?    
• Fewer  unintended  consequences  from  code  changes  
and  more  flexibility  in  your  systems.  

 SimUDuck  
• fly()  and  quack()  vary  across  ducks  
• Pull  methods  out  of  Duck  class  and  create  new  set  of  
classes  to  represent  each  behaviour.  

FEUP ● Nuno Flores ●


14

7
9/22/11

Designing  the  behaviours   an


am to
Progr ace, not
nterf
 “Program  to  an  interface,  not  an  implementation”   ian ation
!
• Behaviours  will  live  in  a  separate  class…   m p l e ment
i
• …a  class  that  implements  a  particular  behaviour  interface.  

 REUSE  
• Everyone  besides  “ducks”  can  use  the  behaviours.  
• We  can  add  new  behaviours  without  touching  anything.  
• All  of  this  without  the  inheritance  baggage.  

<<interface>>
<<interface>> QuackBehaviour
FlyBehaviour
quack()
fly()

FlyWithWings FlyNoWay Quack Squeak MuteQuack

fly() { fly() { quack() { quack() { quack() {


// implements duck flying // do nothing - can’t fly // duck quacking // rubber duck squeak // can’t quack
} } } } }

FEUP ● Nuno Flores ●


15

Duck
Integrating  changes…   FlyBehaviour flyBehaviour
QuackBehaviour quackBehaviour

performQuack()
1. Add  behaviour  holders   swim()
display()
performFly()
2. Implement  performQuack()   //OTHER duck-like methods
public class Duck {

QuackBehavior quackBehavior;
// more

public void performQuack() {


quackBehavior.quack();
}
}
3. Set  behaviours  accordingly  
public class MallardDuck extends Duck {

public MallardDuck() {
quackBehavior = new Quack();
flyBehavior = new FlyWithWings();
}

public void display() {


System.out.println("I'm a real Mallard duck");
}
}
FEUP ● Nuno Flores ●
16

8
9/22/11

Setting  behaviour  dynamically…  


Duck
FlyBehaviour flyBehaviour
1. Add  setters  to  the  Duck  class.   QuackBehaviour quackBehaviour

performQuack()
public void setFlyBehavior (FlyBehavior fb) { swim()
flyBehavior = fb; display()
} performFly()
public void setQuackBehavior(QuackBehavior qb) { setFlyBehaviour()
quackBehavior = qb; setQuackBehaviour()
} //OTHER duck-like methods

2. Make  new  Duck  Type  (ModelDuck).  


public class ModelDuck extends Duck {
public ModelDuck() {
flyBehavior = new FlyNoWay();
quackBehavior = new Quack();
}
public void display() {
System.out.println("I'm a model duck");
}
}
3. Make  a  new  FlyBehaviour  Type.  
public class FlyRocketPowered implements FlyBehavior {
  public void fly() {
System.out.println("I'm flying with a rocket");
}
}

FEUP ● Nuno Flores ●


17

…and  try  it  out!  


4. Write  some  testing  code  
public class MiniDuckSimulator {
public static void main(String[] args) {

Duck mallard = new MallardDuck();


mallard.performQuack();
mallard.performFly();

Duck model = new ModelDuck();

model.performFly();

model.setFlyBehavior(new FlyRocketPowered());

model.performFly();
}
}

5. Run  it!  
%java MiniDuckSimulator
Quack
I’m flying
I can’t fly
I’m flying with a rocket
FEUP ● Nuno Flores ●
18

9
9/22/11

Big  Picture  on  encapsulating  behaviours  


<<interface>>
FlyBehaviour
fly()

Family of
algorithms
FlyWithWings FlyNoWay

fly() { fly() {
// implements duck flying // do nothing - can’t fly
} }

Duck
<<interface>>
FlyBehaviour flyBehaviour QuackBehaviour
QuackBehaviour quackBehaviour quack()
performQuack()
swim()
display()
performFly()
Quack Squeak MuteQuack
setFlyBehaviour()
setQuackBehaviour() quack() { quack() { quack() {
//OTHER duck-like methods // duck quacking // rubber duck squeak // can’t quack
} } }

MallardDuck RedheadDuck RubberDuck DecoyDuck


These
display() { display() { display() { display() { “algorithms” are
// looks like a mallard } // looks like a redhead } // looks like a rubberduck // looks like a decoyduck interchangable
} }

FEUP ● Nuno Flores ●


19

HAS-­‐A  can  be  better  than  IS-­‐A  


Favor sition
compo
 “Each  duck  has  a  FlyBehaviour  and  a   over tance.!
i
QuackBehaviour  to  which  it  delegates  flying   inher
and  quacking”  
 “Favor  composition  over  inheritance”  
 Creating  systems  using  compostion  gives  
more  flexibility.  
• Encapsulates  related  family  of  algorithms  
• Change  behaviour  at  runtime  
• Used  throughout  many  design  patterns  

FEUP ● Nuno Flores ●


20

10
9/22/11

Maybe  you  noticed…   defin


es a
,
t r a t egy - lgorithms and
S
i l y of a each one,
fa m es
 You  have  used  a  design  pattern   sulat
encap s them trateg
y
m a k e e a ble. S ary
back  there   ha n g v
interc e algorithmrom clients
lets thendently f
 STRATEGY  pattern   indep se it.!
that u
• defines  a  family  of  algorithms,  
encapsulates  each  one,  and  makes  
them  interchangeable.  Strategy  lets  
the  algorithm  vary  independently  from  
clients  that  use  it.  

FEUP ● Nuno Flores ●


21

Design  Puzzle  
 Each  character  can  make  use  of  one  weapon  at  a  time.  
 A  character  can  change  weapons  at  any  time  during  the  
game.  

Troll Knight SwordBehaviour BowAndArrowBehaviour

fight() { … } fight() { … } useWeapon() { useWeapon() {


// implements slashing with a // implements shooting with bow
sword and arrow
} }
Character
King
WeaponBehaviour weapon AxeBehaviour
fight() { … } KnifeBehaviour
fight() useWeapon() { useWeapon() {
// implements cutting with na axe // implements cutting with a knife
} }
Queen
fight() { … }
WeaponBehaviour
setWeapon(WeaponBehaviour w) {
this.weapon = w; useWeapon()
}

FEUP ● Nuno Flores ●


22

11
9/22/11

A  shared  vocabulary…  
 Shared  pattern  vocabularies  are  POWERFUL.  
• Its  the  lingo,  man…  

 Patterns  allow  you  to  say  more  with  less.  


• One  word,  lots  of  information  

 Talking  at  the  pattern  level  allows  you  to  stay  “in  the  design”  
for  longer.  
• How  many  design  meetings  have  you  been  in  that  quicly  degrade  into  
implementation  details?  

 Can  turbo  charge  your  development  team.  


• Less  room  for  misunderstanding  
• Community  of  pattern  users  

 Encourage  more  junior  developers  to  get  up  to  speed.  


• Bring  them  into  the  community  
FEUP ● Nuno Flores ●
23

Don’t  forget…  
 Design  Patterns  are  more  than  good  OO  design  principles  
 Knowing  the  OO  Basics  doesn’t  make  you  a  good  designer.  
 A  design  guru  thinks  about  how  to  create  flexible  designs  
that  are  maintainable  and  can  cope  with  change.  

FEUP ● Nuno Flores ●


24

12
9/22/11

Design  Billboard   OO Ba
sics!
Abstr
action
!
Encap
sulatio
OO Principles! Polym n!
es a orphis
defin hms, m!
egy - t Inherit
Strat y of algori h one, and
Encapsulate what varies.! ance!
Favor composition over inheritance.! famil sulates eac
encap s them tegy
. Stra
Program to interfaces, not make hangeable vary
implementations.! interc e algorithmrom clients
lets thendently f
indep se it.!
that u

FEUP ● Nuno Flores ●


25

Challenge    
 Now  Ducks  can  dive.  
• What  would  that  change?  

 Make  that  Ducks  can  dive…  

FEUP ● Nuno Flores ●


26

13
9/22/11

Weather  Monitoring  Station  


 Create  na  app  that  uses  the  WeatherData  object  to  update  
three  displays  for  current  condition,  weather  stats,  and  a  
forecast.  

WeatherData
Humidity object
sensor device
pulls data displays

Temperature
sensor device
WEATHER STATION

Pressure At least, three


Client provides… What we implement… different
sensor device
displays…

FEUP ● Nuno Flores ●


27

Weather  Monitoring  Station  


WeatherData
getTemperature()
getHumidity() /*
getPressure() * This method gets called
measurementsChanged() * whenever the weather measurements
* have been updated
// other methods *
*/
public void measurementsChanged() {
// Your code goes here
}

 Our  job  
• Implement  measurementsChanged()  so  that  it  updates  the  three  
displays  for  current  conditions,  weather  stats,  and  forecast.  

 What  do  we  know  so  far?  


• Three  getter  methods  for  all  measurements  
• measurementsChanged()  is  called  (somehow)  when  these  change.  
• We  need  three  display  elements  that  must  be  updated  on  new  
measurements  
• The  system  must  be  expandable  to  new  displays.  

FEUP ● Nuno Flores ●


28

14
9/22/11

“We  need  it  yesterday”  approach…    


public class WeatherData {
// instance variable declarations here…
public void measurementsChanged() {

float temp = getTemperature();


float humidity = getHumidity();
float pressure = getPressure();

currentConditionsDisplay.update(temp, humidity, pressure);


statisticsConditionsDisplay.update(temp, humidity, pressure);
forecastConditionsDisplay.update(temp, humidity, pressure);

}
// other WeatherData methods here…
}

 What  is  wrong  with  this  implementation?  


A. We  are  coding  to  concrete  implementations,  not  interfaces  
B. For  every  new  display  element  we  need  to  alter  code.  
C. We  have  no  way  to  add  (or  remove)  display  elements  at  runtime.  
D. The  display  element  don’t  implement  a  common  interface.  
E. We  haven’t  encapsulated  the  part  that  changes  
F. We  are  violating  encapsulation  of  the  WeaherData  class.  
FEUP ● Nuno Flores ●
29

OBSERVER  pattern   a one-


to-
- d e fines between
 Publishers  +  Subscribers  =  Observer  Pattern   ve r
Obser dependen en one
cy
• Subscribers  register  themselves  to  Publishers  as   many so that wh ate, all of
s
“Observers”   object changes st e notified
r
object endents a
p
• Publisher  notify  registered  subscribers  when   its de pdated
“publishing”.   and u atically.!
autom
 The  Observer  pattern  defines  a  one-­‐to-­‐many  
relatioship  between  a  set  of  objects.  
 When  the  state  of  one  object  changes,  all  of  its  
dependents  are  notified.  

FEUP ● Nuno Flores ●


30

15
9/22/11

The  power  of  Loose  Coupling   oosely


e for l
Striv d designs
 When  two  objects  are  loosely  coupled,  they  can   e
coupl n objects
e
interact  but  have  very  little  knowledge  of  each  other.   betwe teract.
n
that i
 The  Observer  pattern  provides  this.  Why?  
• The  only  thing  the  subject  know  about  an  observer  is  that  it  
implements  a  certain  interface.  
• We  can  add  new  observers  at  any  time.  
• We  never  need  to  modify  the  subject  to  add  new  types  of  
observers.  
• We  can  reuse  subjects  or  observers  independently  of  each  
other.  
• Changes  to  either  subject  or  observer  will  not  affect  the  other.  

 Loosely  coupled  designs  allow  us  to  build  flexible  OO  


systems  that  can  handle  change  because  the  minimize  
interdependency  between  objects.  

FEUP ● Nuno Flores ●


31

Designing  the  Weather  Station…  


Subject observers
Observer DisplayElement
registerObserver()
notify() display()
removeObserver()
notifyObservers()

CurrentConditionsDisplay

update()
subject display() { // display current
WeatherData measurements
}
registerObserver()
removeObserver()
notifyObservers() subject
StatisticsDisplay
getTemperature()
getHumidity() subject update()
getPressure() display() { // display
measurementsChanged() measurements statistics
}
subject

ForecastDisplay

update()
display() { // display the
forecast
}

ThirdPartyDisplay

update()
display() { // display other
measurement related values
}

FEUP ● Nuno Flores ●


32

16
9/22/11

Implementing  the  Weather  Station  (I)  


Subject observers
Observer DisplayElement
registerObserver()
notify() display()
removeObserver()
notifyObservers()

CurrentConditionsDisplay

 Interface  classes  
update()
subject display() { // display current
WeatherData measurements
}
registerObserver()
removeObserver()
notifyObservers() subject
StatisticsDisplay
getTemperature()
getHumidity() subject update()
getPressure() display() { // display
measurementsChanged() measurements statistics
}
subject

ForecastDisplay

public interface Subject {


update()
display() { // display the
forecast
}

public void registerObserver(Observer o); update()


ThirdPartyDisplay

display() { // display other

public void removeObserver(Observer o); measurement related values


}

public void notifyObservers();


}

public interface Observer {


public void update(float temp, float humidity, float pressure);
}
public interface DisplayElement {
public void display();
}

FEUP ● Nuno Flores ●


33

Implementing  the  Weather  Station  (II)  


Subject observers
Observer DisplayElement

public class WeatherData implements Subject {


registerObserver()
notify() display()
removeObserver()
notifyObservers()

CurrentConditionsDisplay

private ArrayList observers; WeatherData

registerObserver()
subject
update()
display() { // display current
measurements
}

private float temperature;


removeObserver()
notifyObservers() subject
StatisticsDisplay
getTemperature()
getHumidity() subject update()

private float humidity;


getPressure() display() { // display
measurementsChanged() measurements statistics
}
subject

ForecastDisplay

private float pressure; update()


display() { // display the
forecast
}

ThirdPartyDisplay

update()

public WeatherData() {
display() { // display other
measurement related values
}

observers = new ArrayList();


}

public void registerObserver(Observer o) {


Subject
observers.add(o); interface
}

public void removeObserver(Observer o) {


int i = observers.indexOf(o);
if (i >= 0) {
observers.remove(i);
}
}

public void notifyObservers() {


for (int i = 0; i < observers.size(); i++) {
Observer observer = (Observer)observers.get(i);
observer.update(temperature, humidity, pressure);
}
}

FEUP ● Nuno Flores ●


34

17
9/22/11

Implementing  the  Weather  Station  (III)  


public void measurementsChanged() {
notifyObservers();
}

public void setMeasurements(float temperature, float humidity, float


pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}

// other WeatherData methods here

public float getTemperature() {


return temperature;
}

public float getHumidity() {


return humidity;
}

public float getPressure() {


Subject observers
Observer DisplayElement
registerObserver()
notify() display()
removeObserver()
notifyObservers()

return pressure; subject


CurrentConditionsDisplay

update()
display() { // display current

}
WeatherData measurements
}
registerObserver()
removeObserver()
notifyObservers() subject
StatisticsDisplay

}
getTemperature()
getHumidity() subject update()
getPressure() display() { // display
measurementsChanged() measurements statistics
}
subject

ForecastDisplay

update()
display() { // display the
forecast
}

ThirdPartyDisplay

update()
display() { // display other
measurement related values
}

FEUP ● Nuno Flores ●


35

Implementing  the  Weather  Station  (IV)  


public class CurrentConditionsDisplay implements Observer, DisplayElement {
private float temperature;
private float humidity;
private Subject weatherData;

public CurrentConditionsDisplay(Subject weatherData) {


this.weatherData = weatherData;
weatherData.registerObserver(this);
}

public void update(float temperature, float humidity, float pressure) {


this.temperature = temperature;
this.humidity = humidity;
display();
}
Observer interface
public void display() {
System.out.println("Current conditions: " + temperature
+ "F degrees and " + humidity + "% humidity");
}
} Display interface
Subject observers
Observer DisplayElement
registerObserver()
notify() display()
removeObserver()
notifyObservers()

CurrentConditionsDisplay

update()
subject display() { // display current
WeatherData measurements
}
registerObserver()
removeObserver()
notifyObservers() subject
StatisticsDisplay
getTemperature()
getHumidity() subject update()
getPressure() display() { // display
measurementsChanged() measurements statistics
}
subject

ForecastDisplay

update()
display() { // display the
forecast
}

ThirdPartyDisplay

update()
display() { // display other
measurement related values
}

FEUP ● Nuno Flores ●


36

18
9/22/11

Using  Java’s  built-­‐in  Observer  Pattern  


 How  it  works  
• For  an  Object  to  become  na  
observer…   observers
Observable
-­‐ Implement  Observer  interface   addObserver()
Observer

and  act  as  usual   deleteObserver()


update()
notifyObserver()
• For  the  Observable  to  send   setChanged()

notifications   GeneralDisplay

-­‐ Extend  class  Observable   subject update()


WeatherData display()
-­‐ First  call  setChanged()  
getTemperature() subject
-­‐ Call  one  of  these   getHumidity()
subject StatisticsDisplay
getPressure()
-­‐ notifyObservers()  
update()
-­‐ notifyObservers(Object  arg)   display()

• For  na  Observer  to  receive   ForecastDisplay


notifications   update()
-­‐ Update(Observable  o,  Object  arg)   display()

-­‐ o  =  subject  
-­‐ arg  =  passed  through  
notifyObservers  or  null  

FEUP ● Nuno Flores ●


37

Reworking  the  Weather  Station  (I)  


import java.util.Observable;
import java.util.Observer;

public class WeatherData extends Observable {


private float temperature;
private float humidity;
private float pressure;

public WeatherData() { }

public void measurementsChanged() {


setChanged();
notifyObservers(); _Pull method_
}

public void setMeasurements(float temperature, float humidity, float pressure) {


this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}

public float getTemperature() {


return temperature;
}

public float getHumidity() {


return humidity;
}

public float getPressure() {


return pressure;
}
}
FEUP ● Nuno Flores ●
38

19
9/22/11

Reworking  the  Weather  Station  (II)  


import java.util.Observable;
import java.util.Observer;

public class CurrentConditionsDisplay implements Observer, DisplayElement {


Observable observable;
private float temperature;
private float humidity;

public CurrentConditionsDisplay(Observable observable) {


this.observable = observable;
observable.addObserver(this);
}

public void update(Observable obs, Object arg) {


if (obs instanceof WeatherData) {
WeatherData weatherData = (WeatherData)obs;
this.temperature = weatherData.getTemperature();
this.humidity = weatherData.getHumidity();
display();
}
}

public void display() {


System.out.println("Current conditions: " + temperature
+ "F degrees and " + humidity + "% humidity");
}
}

FEUP ● Nuno Flores ●


39

Observer  within  JDK…  


 The  dark  side  of  java.util.Observable  
• Observable  is  a  class.  
• Observable  protects  crucial  methods  (ex:  setChanged).  

 Other  sightings  of  the  Observer  pattern:  SWING  


public void init() {
frame = new JFrame();

JButton button = new JButton("Should I do it?");


button.addActionListener(new AngelListener());
button.addActionListener(new DevilListener());
frame.getContentPane().add(BorderLayout.CENTER, button);

// Set frame properties


frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(BorderLayout.CENTER, button);
frame.setSize(300,300);
frame.setVisible(true);
}

class AngelListener implements ActionListener {


public void actionPerformed(ActionEvent event) {
System.out.println("Don't do it, you might regret it!");
}
}

class DevilListener implements ActionListener {


public void actionPerformed(ActionEvent event) {
System.out.println("Come on, do it!");
}
}

FEUP ● Nuno Flores ●


40

20
9/22/11

Design  Billboard   ily


OO Ba
sics!
a fam Abstr
efines psulates action
gy - d ca
Strate orithms, enakes them !
of a lg
e, and
m
Strate
gy Encap
each onhangeable. vary sulatio
OO Principles! interc e algorithm
om cl ients Polym n!
lets th dently fr orphis
en m!
indep se it.!
th at u Inherit
Encapsulate what varies.! ance!
Favor composition over inheritance.!
Program to interfaces, not
implementations.! to-
a one-
Strive for loosely coupled r - d e fines between
ve cy
designs between object that Obser dependen en one
interact.! many so that wh ate, all of
s
object changes st e notified
r
object endents a
p
its de pdated
and u atically.!
autom

FEUP ● Nuno Flores ●


41

Try  it  out  


 Look  at  the  source  code,  and  run  the  WeatherStation  to  see  
the  Observer  at  work.  
 Add  a  new  display  called  “TemperatureLog”  that  keeps  an  
history  of  temperature  readings  and  prints  them  out.  

FEUP ● Nuno Flores ●


42

21
9/22/11

Starbuzz  Coffee  
 Famous  fast-­‐growing  coffee  shop  
 Initial  design  
Beverage
description

getDescription()
cost()

// other useful methods

HouseBlend DarkRoast Decaf Espresso

cost() cost() cost() cost()

FEUP ● Nuno Flores ●


43

Starbuzz  Coffee  
 You  can  also  ask  for  condiments  (steamed  milk,  soy,  
“mocha”)  all  topped  with  whipped  milk.  
 Each  one  has  cost  increments.  
 Can  you  say  “class  explosion”?  
Beverage
description

getDescription()
cost()

// other useful methods

HouseBlendWithSteamedMilk
andMocha
DarkRoastWithSteamedMilka EspressoWithSteamedMilkan
cost() dMocha
ndMocha
cost() cost()

HouseBlendWithSteamedMilk HouseBlendWithSteamedMilk DecafWithSteamedMilkandMo


EspressoWithWhip
andCaramel andMocha cha
cost() cost() cost() cost()

DecafWithSteamedMilkandCa EspressoWithSteamedMilkan
DarkRosWithSteamedMilkand ramel dMocha
HouseBlendWithWhip
Caramel
cost() cost()
cost() cost()

And there DecafWithSteamedMilkandMo EspressoWithSteamedMilkan


DarkRoastWithSoyAndMocha
are still a HouseBlendWithSoy cha
cost()
dCaramel

cost() cost()
few missing… cost()

DarkRoastWithSteamedMilka DecafWithWhip
HouseBlendWithSoyAndMoc ndMocha
ha cost()
cost()
cost()

DarkRoastWithSoyAndMocha DecaftWithSoyAndMocha
DarkRoastWithSoy
cost() cost() FEUP ● Nuno Flores ●
cost() 44

22
9/22/11

Starbuzz  Coffee  
 One  way  of  solving  things…  
Beverage
description new boolean for
milk each condiment
soy
mocha
whip

getDescription() cost() is not abstract


cost() now. Calculates
setters/ costs of condiments
getters for hasMilk()
condiments setMilk()
hasSoy()
setSoy() subclasses implement cost()
hasMocha() to compute cost of beverage
setMocha() and call superclass to add
hasWhip() condiment cost
setWhip()

// other useful methods

HouseBlend DarkRoast Decaf Espresso

cost() cost() cost() cost()

FEUP ● Nuno Flores ●


45

Starbuzz  Coffee  
 Implemented  would  look  like…  
public class Beverage {
// instance variable milkCost, soyCost, mochaCost and whipCost.
public float cost() {

float condimentCost = 0.0;


if (hasMilk()) {
condimentCost += milkCost;
}
if (hasSoy()) {
condimentCost += soyCost;
}
if (hasMocha()) {
condimentCost += mochaCost;
}
if (hasWhip()) {
condimentCost += whipCost;
}
}
}

public class DarkRoast extends Beverage {

public DarkRoast() {
description = “Most Excellent Dark Roast”;
}

public float cost() {


return 1.99 + super.cost();
}
}

FEUP ● Nuno Flores ●


46

23
9/22/11

Starbuzz  Coffee  
 Design  impacts  
• Price  changes  for  condiments  
-­‐ Force  to  alter  existing  code.  
• New  condiments    
-­‐ Force  to  add  new  methods  and  alter  the  cost  method  in  the  superclass.  
• New  beverages  
-­‐ Some  condiment  may  not  be  appropriate  (iced  tea  with  mocha???).  
-­‐ Subclasses  will  inherit  superflous  code.  
• What  if  a  customer  wants  a  double  mocha?  

FEUP ● Nuno Flores ●


47

The  Open-­‐Closed  Principle   d be


shoul ,
C lasses r extension
 Allow  classes  to  be  easily  extended  to  incorporate  new   open fo for
osed
behaviour  without  modifying  existing  code.     but cl ication.!
mo d i f
 Contradictory??  How  can  a  design  have  that??  
• Flexibility  and  resilience  to  change.  
• enough  to  take  on  new  functionality  to  meet  changing  
requirements  

 Techniques  for  allowing  code  to  be  extended  without  


direct  modification.  
 WARNING!  
• Applying  the  Open-­‐Closed  principle  EVERYWHERE  is  wasteful  
-­‐ Leads  to  complex,  hard  to  understand  code.  
• Apply  only  to  those  parts  that  are  most  likely  to  change.  

FEUP ● Nuno Flores ●


48

24
9/22/11

Back  to  the  Starbuzz  Coffee…  


 Meet  the  DECORATOR  pattern   DarkRoast

1. Take  a  DarkRoast  object   cost()

2. Decorate  it  with  a  Mocha  object  


DarkRoast

cost()
3. Decorate  it  with  a  Whip  object   cost()

Mocha

4. Call  the  cost()  method  and  rely  on   Decorator. It is the same type
as DarkRoast (Beverage)

delegation  to  add  the  condiments  costs  

DarkRoast
cost() cost() cost()
Mocha
Whip

€1,29 cost() cost() cost() Decorator. Still the same type


.99 as DarkRoast and Mocha
DarkRoast (Beverage). So we can do
.20 Mocha everything like a Beverage.
Whip

FEUP ● Nuno Flores ●


49

DECORATOR  pattern  
h
Attac sibilities
 Decorators  have  the  same  supertype  as  the  object  they   ator - n
Decor onal respo mically.
decorate.   i a
addit object dyn e flexible
• We  can  pass  a  decorated  object  in  place  of  the  original  (wrapped)   to an tors provid classing
a b
object   Decor ative to su
a l t e r n n g
tendi
 Objects  can  be  decorated  at  anytime   for ex ionality.!
fu n c t
• At  runtime  with  as  many  as  we  want.  

 Decorators  add  their  own  behaviour  either  before  and/or  


after  delegating  to  the  object  they  decorate  to  do  the  rest  
of  the  job.  

FEUP ● Nuno Flores ●


50

25
9/22/11

Starbuzz  Coffee  using  DECORATOR  

Beverage
description
getDescription()
cost() component
// other useful methods

HouseBlend DarkRoast
CondimentDecorator
cost() cost()
getDescription()

Decaf Espresso

cost() cost()

Milk Mocha Soy Whip


Why does it need to
Beverage beverage Beverage beverage Beverage beverage Beverage beverage
implement getDescription()?
cost() cost() cost() cost()
getDescription() getDescription() getDescription() getDescription()

FEUP ● Nuno Flores ●


51

Beverage
description
getDescription()

Writing  the  Starbuzz  code…  


cost() component
// other useful methods

HouseBlend DarkRoast
CondimentDecorator
cost() cost()
getDescription()

Decaf Espresso

cost() cost()

Milk Mocha Soy Whip

Beverage beverage Beverage beverage Beverage beverage Beverage beverage

 Base  classes  
cost() cost() cost() cost()
getDescription() getDescription() getDescription() getDescription()

public abstract class Beverage {


String description = "Unknown Beverage";

public String getDescription() {


return description;
}

public abstract double cost();


}

public abstract class CondimentDecorator extends Beverage {


public abstract String getDescription();
}

FEUP ● Nuno Flores ●


52

26
9/22/11

Beverage
description
getDescription()

Writing  the  Starbuzz  code…  


cost() component
// other useful methods

HouseBlend DarkRoast
CondimentDecorator
cost() cost()
getDescription()

Decaf Espresso

cost() cost()

Milk Mocha Soy Whip

Beverage beverage Beverage beverage Beverage beverage Beverage beverage

 Some  beverage  sub-­‐classes  


cost() cost() cost() cost()
getDescription() getDescription() getDescription() getDescription()

public class Espresso extends Beverage {

public Espresso() {
description = "Espresso";
}

public double cost() {


return 1.99;
}
}

public class HouseBlend extends Beverage {

public HouseBlend() {
description = "House Blend Coffee";
}

public double cost() {


return .89;
}
}

FEUP ● Nuno Flores ●


53

Beverage
description
getDescription()

Writing  the  Starbuzz  code…  


cost() component
// other useful methods

HouseBlend DarkRoast
CondimentDecorator
cost() cost()
getDescription()

Decaf Espresso

cost() cost()

Milk Mocha Soy Whip

Beverage beverage Beverage beverage Beverage beverage Beverage beverage

 Example  of  Condiment  Concrete  Decorator  


cost() cost() cost() cost()
getDescription() getDescription() getDescription() getDescription()

public class Mocha extends CondimentDecorator {


Beverage beverage;

public Mocha(Beverage beverage) {


this.beverage = beverage;
}

public String getDescription() {


return beverage.getDescription() + ", Mocha";
}

public double cost() {


return .20 + beverage.cost();
}
}

FEUP ● Nuno Flores ●


54

27
9/22/11

Serving  some  coffees…  


public class StarbuzzCoffee {

public static void main(String args[]) {

Beverage beverage = new Espresso();


System.out.println(beverage.getDescription()
+ " $" + beverage.cost());

Beverage beverage2 = new DarkRoast();


beverage2 = new Mocha(beverage2);
beverage2 = new Mocha(beverage2);
beverage2 = new Whip(beverage2);
System.out.println(beverage2.getDescription()
+ " $" + beverage2.cost());

Beverage beverage3 = new HouseBlend();


beverage3 = new Soy(beverage3);
beverage3 = new Mocha(beverage3);
beverage3 = new Whip(beverage3);
System.out.println(beverage3.getDescription()
+ " $" + beverage3.cost());
}
}
%java StarbuzzCoffee
Espresso $1.99
Dark Roast Coffee, Mocha, Mocah, Whip $1.49
House Blend Coffee, Soy, Mocha, Whip $1.34
FEUP ● Nuno Flores ●
55

Design  Challenge  
 Starbuzz  coffees  now  have  sizes.  
• “tall”  (small)  
• “grande”  (medium)  
• “venti”  (large)  

 They’ve  added  two  methods  to  the  Beverage  Class  


• setSize()  and  getSize()  

 They  would  like  the  condiments  to  be  charged  according  to  
size  
• Ex:  Mocha  costa  .10,  .15,  .20  respectively  for  tall,  grande  and  venti  
coffees.  

 What  modifications  in  the  decorator  classes  would  you  do  to  
handle  these  new  requirements?  (really  do  it    )  

FEUP ● Nuno Flores ●


56

28
9/22/11

Other  DECORATOR  sightings…  


 JAVA  I/O  
InputStream

FileInputStream StringBufferInputStream ByteArrayInputStream FilterArrayInputStream

PushbackInputStream BufferedInputStream DataInputStream LineNumberInputStream

 How  to  write  your  own  Java  I/O  Decorator  


• Implement  the  “read”  methods.  

 Downsides  
• Watch  out  for  large  number  of  subclasses  
-­‐ Can  become  overwhelming  
• Keep  it  in  perspective  

FEUP ● Nuno Flores ●


57

Design  Billboard   ily


OO Ba
sics!
a fam Abstr
efines psulates action
gy - d ca
Strate orithms, enakes them !
of alg e, and m Strategy Encap
each onon geabl
e. sulatio
OO Principles! d ef
rchane- m vary
ininesteathe algorith from clients Polym n!
bs e r ver ependen
- letscy dently orphis
O any d in
o dep
th
en
at it.! m !
to-m n ob
s
jects that u
an gse
es Inherit
Encapsulate what varies.! betwee e object ch ents ance!
on epend
when all of its d updated
te , d
Favor composition over inheritance.! satare notified llany.!
atica
autom
Program to interfaces, not
implementations.!
Strive for loosely coupled h
designs between object that Attac sibilities
ator - n
interact.! Decor onal respo mically.
i a
Classes should be open for addit object dyn e flexible
extension but closed for to an tors provid classing
a b
modification.! Decor ative to su
altern ending
t
for ex ionality.!
funct

FEUP ● Nuno Flores ●


58

29
9/22/11

Pizza  Shop  
 Imagine  a  pizza  shop  where  you  might  order  pizzas…  
Pizza orderPizza() {

Pizza pizza = new Pizza();

pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}

 But  you  need  more  than  one  type  of  pizza…  


Pizza orderPizza(String type) {

Pizza pizza;

if (type.equals(“cheese”)) {
pizza = new CheesePizza();
} else if (type.equals(“greek”)) {
pizza = new GreekPizza();
} else if (type.equals(“pepperoni”)) {
pizza = new PepperoniPizza();
}

pizza.prepare();
. . .
} FEUP ● Nuno Flores ●
59

Pizza  Shop  
 But  the  pressure  is  on  to  add  more  pizza  types  
Pizza orderPizza() {

Pizza pizza; This code is NOT


closed for modification.
if (type.equals(“cheese”)) {
pizza = new CheesePizza();
} else if (type.equals(“greek”)) {
pizza = new GreekPizza();
What varies
} else if (type.equals(“pepperoni”)) {
pizza = new PepperoniPizza();
} else if (type.equals(“clam”)) {
pizza = new ClamPizza();
} else if (type.equals(“veggie”)) {
pizza = new VeggiePizza();

pizza.prepare();
What stays pizza.bake();
the same pizza.cut();
pizza.box();
return pizza;
}

 Identify  what  varies  and  what  stays  the  same    


FEUP ● Nuno Flores ●
60

30
9/22/11

Not yet the design pattern

Encapsulation  object  creation  


we’re looking for

Pizza orderPizza() { public class SimplePizzaFactory


Pizza pizza;
public Pizza createPizza(String type)
if (type.equals(“cheese”)) {
pizza = new CheesePizza();
} else if (type.equals(“greek”)) { Pizza pizza = null;
pizza = new GreekPizza();
} else if (type.equals(“pepperoni”)) { if (type.equals(“cheese”)) {
pizza = new PepperoniPizza();
} else if (type.equals(“clam”)) { pizza = new CheesePizza();
pizza = new ClamPizza(); } else if (type.equals(“greek”)) {
} else if (type.equals(“veggie”)) { pizza = new GreekPizza();
pizza = new VeggiePizza();
} else if (type.equals(“pepperoni”)) {
pizza.prepare(); pizza = new PepperoniPizza();
pizza.bake(); } else if (type.equals(“clam”)) {
pizza.cut();
pizza.box(); pizza = new ClamPizza();
return pizza; } else if (type.equals(“veggie”)) {
} pizza = new VeggiePizza();
}
return pizza;
}
public class PizzaStore
SimplePizzaFactory factory;

public PizzaStore(SimplePizzaFactory factory) {


this.factory = factory;  We  call  this  a  SimpleFactory  
}
• Not  a  really  design  pattern  but  an  honorable  
Pizza orderPizza() { mention  
Pizza pizza;
Pizza
Pizza = factory.createPizza(type); PizzaStore SimplePizzaFactory
prepare()
orderPizza() createPizza() bake()
pizza.prepare(); cut()
box()
pizza.bake();
pizza.cut();
pizza.box(); CheesePizza PepperoniPizza

return pizza; VeggiePizza ClamPizza


}
FEUP ● Nuno Flores ●
61

Franshising  the  pizza  store  


 We  want  to  have  regional  preferences…  
• Different  style  of  pizzas  (New  York,  Chicago,  …)  
-­‐ Several  factories…  
NYPizzaFactory nyFactory = new NYPizzaFactory();
Pizzatore nyStore = new PizzaStore(nyFactory);
nyStore.order(“veggie”);

 But  still  lacks  flexibility…  


• What  if  the  rest  of  the  process  changes?  (baking,  cutting,  boxing…)  

 Solution:  Building  a  framework  for  the  pizza  store  and  let  the  
subclasses  decide.  
 

FEUP ● Nuno Flores ●


62

31
9/22/11

Allowing  subclasses  to  decide  


 Inserting  a  “factory  method”  into  PizzaStore  class  
public abstract class PizzaStore

Pizza orderPizza(String type) {


Pizza pizza;

Pizza = createPizza(type); createPizza() is back to


PizzaStore rather than on a
pizza.prepare(); factory object
pizza.bake();
pizza.cut();
pizza.box();

return pizza;
We’ve moved our factory
abstract Pizza createPizza(String type); object to this method
}
Our “factory method” is now
abstract in PizzaStore

PizzaStore

createPizza()
orderPizza()

Each subclass decide


what type of pizzas it
They MUST implement NYStylePizzaStore ChicagoStylePizzaStore creates by implementing
createPizza() because is its own createPizza()
createPizza() createPizza()
abstract on the base class
FEUP ● Nuno Flores ●
63

Making  a  PizzaStore  
 NewYork  style  pizza  store  
NYPizzaStore extends PizzaStore,
so it inherits the orderPizza()
createPizza() return a Pizza, and method (among others)
the subclass if fully responsible for
which concrete Pizza it
instantiates
public class NYPizzaStore extends PizzaStore {

Pizza createPizza(String item) {


if (item.equals("cheese")) {
return new NYStyleCheesePizza();
} else if (item.equals("veggie")) { Here’s where we create
return new NYStyleVeggiePizza(); our concrete classes.
For each type of Pizza
} else if (item.equals("clam")) { we create the NY style
return new NYStyleClamPizza();
} else if (item.equals("pepperoni")) {
return new NYStylePepperoniPizza();
} else return null;
}
}

 Note:  
• orderPizza()  method  in  the  superclass  has  no  clue  which  Pizza  we  are  
creating.  It  just  knows  it  can  prepare,  bake,  cut  and  box  it!  

FEUP ● Nuno Flores ●


64

32
9/22/11

Now  we’re  just  missing  Pizzas…  


 First,  the  base  class  (what  doesn’t  vary…)  
public abstract class Pizza {
String name;
String dough;
String sauce;
ArrayList toppings = new ArrayList();

void prepare() {
System.out.println("Preparing " + name);
System.out.println("Tossing dough...");
System.out.println("Adding sauce...");
System.out.println("Adding toppings: ");
for (int i = 0; i < toppings.size(); i++) {
System.out.println(" " + toppings.get(i));
}
}

void bake() {
System.out.println("Bake for 25 minutes at 350");
}

void cut() {
System.out.println("Cutting the pizza into diagonal slices");
}

void box() {
System.out.println("Place pizza in official PizzaStore box");
}

public String getName() {


return name;
}
FEUP ● Nuno Flores ●
65

Now  we’re  just  missing  Pizzas…  


 Now  some  concrete  classes  (customizing  what  varies…)  
public class NYStyleCheesePizza extends Pizza { Pizza

name
dough
public NYStyleCheesePizza() { sauce
toppings

prepare()
name = "NY Style Sauce and Cheese Pizza"; bake()
dough = "Thin Crust Dough"; cut()
box()
sauce = "Marinara Sauce";

toppings.add("Grated Reggiano Cheese"); NYStyleCheesePizza


ChicagoStyleCheesePizza Other pizza styles...
} cut()
}

public class ChicagoStyleCheesePizza extends Pizza {

public ChicagoStyleCheesePizza() {
Defining its own style
name = "Chicago Style Deep Dish Cheese Pizza";
dough = "Extra Thick Crust Dough";
sauce = "Plum Tomato Sauce";

toppings.add("Shredded Mozzarella Cheese");


}
It also overrides cut() because it
has own way of cutting
void cut() {
System.out.println("Cutting the pizza into square slices");
}
}
FEUP ● Nuno Flores ●
66

33
9/22/11

Meet  the  FACTORY  METHOD  pattern…  


 The  Creator  classes  
It defines an abstract fectory PizzaStore
The abstract creator never
method for subclasses to createPizza() really knows which concrete
implement to create products orderPizza() product was produced

NYStylePizzaStore ChicagoStylePizzaStore

createPizza() createPizza()

The createPizza() method


is our factory method. It
produces products. These are called
concrete creators

Factories produce products,


and in the PizzaStore, our
 The  Product  classes   Pizza product is a Pizza

These are the concrete


products – all the pizzas
produced by our stores NYStyleCheesePizza ChicagoStyleCheesePizza

NYStylePepperoniPizza ChicagoStylePepperoniPizza

NYStyleClamPizza ChicagoStyleClamPizza

NYStyleVeggiePizza ChicagoStyleVeggiePizza

FEUP ● Nuno Flores ●


67

The  official  definition…   t


Defin
e an
hod - ing an
ry M e t
 Encapsulate  the  instantiations  of  concrete   Facto ace for crea classes
interf but let sub s to
types   object which cla ory
e
s
t
decid tiate. Fac ss defer
n
 Let’s  subclasses  decide   insta d lets a cla the
Metho tiation to
n
• “decide”  doesn’t  mean  at  runtime   insta sses.!
a
subcl
• The  creator  class  is  written  without  knowledge  of  the  
actual  products  to  be  created.  
• The  production  is  decided  purely  by  the  subclass.  

FEUP ● Nuno Flores ●


68

34
9/22/11

The  Dependency  Inversion  Principle  


n
d upo
 High-­‐level  components  should  not  depend  on  low-­‐ Depen ctions. Do
level  components.   abstra pend upon
e
not d te classes.!
Class
A

• They  should  depend  on  abstractions.   c r e


c o n
Class
A Abstract
Class Class AA
C
Class
D Class
C
Class
Class D
B Class
F Class
Class
B Class
E
F
Class
E

 A  few  guidelines  for  follow  this  principle  


• No  variable  should  hold  a  reference  to  a  concrete  class  
• No  class  should  derive  from  a  concrete  class  
• No  method  should  override  an  implementation  method  of  any  
of  its  base  classes.  
-­‐ Override  doesn’t  mean  implement,  its  means  reimplement.  
• Note:  these  are  only  guidelines…  

FEUP ● Nuno Flores ●


69

Challenge  
 Look  at  the  code  and  create  a  PortuguesePizzaStore  
• factory.pizzafm  
• Produces  pizzas  on  a  Portuguese  style…  
• Make  Joaquim  order  some  portuguese  pizzas  (test  drive…)  

FEUP ● Nuno Flores ●


70

35
9/22/11

Meanwhile,  back  at  the  PizzaStore…  


 Keep  the  quality  of  the  pizza’s  ingredients  
• Built  a  Factory  that  produces  ingredients??  
• New  York  uses  a  set  of  ingredients  and  Chicago  another.  
• Soon,  other  regions  will  have  their  different  set  of  ingredients.  

 How  to  handle  families  of  ingredients?  

CHICAGO
NEW YORK Calamari

FrozenClams
FreshClams

BruschettaSauce VeruThinCrust

ThickCrustDough
PlumTomatoSauce
MarinaraSauce ReggianoCheese

GoatCheese

MozarellaCheese
ThinCrustDough

CALIFORNIA

FEUP ● Nuno Flores ●


71

Building  the  ingredient  factories  


 Factory  interface  
public interface PizzaIngredientFactory {
For each ingredient we define a
public Dough createDough(); create method on our interface
public Sauce createSauce();
public Cheese createCheese();
public Veggies[] createVeggies();
public Pepperoni createPepperoni();
public Clams createClam();

} If we had some common “machinery”


Lots of new classes here, to implement in each instance of
one per ingredient factory, we could have made this na
abstract class instead

 Next  steps:  
1. Build  a  factory  for  each  region,  subclassing  from  
PizzaIngredientFactory  and  implementing  all  create  methods  
2. Implement  a  set  of  ingredients  classes  to  be  used  with  the  factory.  
These  can  be  used  among  regions  where  appropriate.  
3. Refactoring  PizzaStore  to  hook  up  these  factories.  

FEUP ● Nuno Flores ●


72

36
9/22/11

Building  the  New  York  ingredient  factory  


The NY ingredient factory implements
the interface for all ingredient factories

public class NYPizzaIngredientFactory implements PizzaIngredientFactory {

public Dough createDough() {


return new ThinCrustDough();
}

public Sauce createSauce() { For each ingredient in the


return new MarinaraSauce(); ingredient family, we create the
} New York version

public Cheese createCheese() {


return new ReggianoCheese();
}

public Veggies[] createVeggies() {


Veggies veggies[] = { new Garlic(), new Onion(), new Mushroom(),
new RedPepper() };
return veggies;
}

public Pepperoni createPepperoni() {


return new SlicedPepperoni();
}

public Clams createClam() {


return new FreshClams();
}
}

FEUP ● Nuno Flores ●


73

Reworking  the  pizzas…  


public abstract class Pizza {
String name;

Dough dough; Each pizza holds a set of ingredients


Sauce sauce; that are used in its preparation
Veggies veggies[];
Cheese cheese;
Pepperoni pepperoni; We’ve now made the prepare method
Clams clam; abstract. This is where we are going to
collect the ingredients for the pizza, which
abstract void prepare(); will come from the ingredient factory

void bake() {
System.out.println("Bake for 25 minutes at 350");
}

void cut() {
System.out.println("Cutting the pizza into diagonal slices");
}

void box() {
System.out.println("Place pizza in official PizzaStore box");
}

void setName(String name) {


this.name = name;
} Other methods remain the same

String getName() {
return name;
}

public String toString() {


// code to print pizza here
}
} FEUP ● Nuno Flores ●
74

37
9/22/11

Reworking  the  pizzas,  continued…  


 Concrete  pizzas…  
public class CheesePizza extends Pizza { To make a pizza now, we need a factory
to provide the ingredients, which passed
through the constructor and stored.
PizzaIngredientFactory ingredientFactory;

public CheesePizza(PizzaIngredientFactory ingredientFactory) {


this.ingredientFactory = ingredientFactory;
}

void prepare() {
System.out.println("Preparing " + name);
dough = ingredientFactory.createDough();
sauce = ingredientFactory.createSauce();
cheese = ingredientFactory.createCheese();
}
} The prepare() method steps through creating a Here’s where the magic happens!
cheese pizza, and each time it needs a
ingredient, it asks the factory to produce it

FEUP ● Nuno Flores ●


75

Revisiting  our  pizza  stores…  


The NY Store is composed with a NY
pizza ingredient factory. This will be
public class NYPizzaStore extends PizzaStore { used to produce the ingredients for all
NY style pizzas
protected Pizza createPizza(String item) {
Pizza pizza = null;
PizzaIngredientFactory ingredientFactory = new NYPizzaIngredientFactory();

if (item.equals("cheese")) { We now pass each pizza the factory that


should de used to produce its ingredients
pizza = new CheesePizza(ingredientFactory);
pizza.setName("New York Style Cheese Pizza");

} else if (item.equals("veggie")) {

pizza = new VeggiePizza(ingredientFactory);


pizza.setName("New York Style Veggie Pizza");

} else if (item.equals("clam")) {
For each type of pizza, we instantiate
pizza = new ClamPizza(ingredientFactory); a new Pizza and give the factory it
pizza.setName("New York Style Clam Pizza"); needs to get its ingredients

} else if (item.equals("pepperoni")) {

pizza = new PepperoniPizza(ingredientFactory);


pizza.setName("New York Style Pepperoni Pizza");

}
return pizza;
}
}

FEUP ● Nuno Flores ●


76

38
9/22/11

Meet  the  ABSTRACT  FACTORY  pattern…  


 What  have  we  done?  
• We  provided  a  means  of  creating  a  
family  of  products  (ingredients).   Defines the interface
for family of products
• We  decoupled  the  code  from  the   Abstract
factories  that  create  the  products.   Provides different
Ingredient
Factory
• Allows  the  implementation  of  a   implementations for same
products
variety  of  product  production  
meant  for  diferent  contexts,  but  
that  has  a  common  interface.  
Chicago
 Because  our  code  is  decoupled  
New York

from  the  actual  products,  we  


can  substitue  different   Pizza made with
ingredients produced
factories  to  get  different   by concrete factory,
but client code
behaviours.   remains the same
PizzaStore

FEUP ● Nuno Flores ●


77

The  official  definition…   -


ctory for
b s tr act Fa interface
A es a n so f
Providng familie ent
creati or depend
d
relate without ete
s concr
object ing their
y
specif s.!
Defines an interface that all Concrete
cl a s s e
factories must implement, which consists of
a set of methods for producing productsl.

This is the product family. Each


concrete factory can produce na The Client is written against
entire set of products the abstract factory and
then composed at runtime
with an concrete factory

Implement different product families.


To create a product. The client uses
one of these factories, so it never has
to instantiate a product object

FEUP ● Nuno Flores ●


78

39
9/22/11

In  terms  of  PizzaStore…   Pizza

prepare()
// other methods

<<interface>>
Dough

ThickCrustDough ThinCrustDough
<<interface>
PizzaIngredientFactory
createDough()
createSuace() <<interface>>
createCheese() Sauce
createVeggies()
createPepperoni()
createClam()

PlumTomatoSauce MarinaraSauce

NYPizzaIngredientFactory ChicagoPizzaIngredientFactory
<<interface>>
createDough() createDough() Cheese
createSuace() createSuace()
createCheese() createCheese()
createVeggies() createVeggies()
createPepperoni() createPepperoni()
createClam() createClam() MozzarellaCheese ReggianoCheese

<<interface>>
Clams

FrozenClams FreshClams

FEUP ● Nuno Flores ●


79

Design  Billboard   ily


OO Ba
sics!
a fam Abstr
efines psulates action
gy - d ca
Strate orithms, enakes them !
of alg e, and m Stttraach tegy Encap
OO Principles! each onon earbl-e.A vary
gto sulatio
ef ininesD echoarane-algn
tea
rc l hm om clnieants
orait Polym n!
d e io to
ver - acy
lets th it
dd denibtlilyities fr
orphis
Obsearny dependsen astpen
dep
ointh
re onit s y.
.! amicall flexible m !
to-m
n ob jects that u gsees dyn
ct
nje ts rs pro vide g Inherit
Encapsulate what varies.! betwee e object ch
aob
enato bclass
in ance!
on dor
Dec
epen e to su
when all of its d upadltaer tendativ g
in
te , d d
Favor composition over inheritance.! satare notified llany.! for exctteionnality.!
atica fun
autom
Program to interfaces, not
implementations.!
Strive for loosely coupled n
fine a
designs between object that
interact.! e t h o d - De g an
ry M tin
Facto ace for crea classes -
Classes should be open for
interf but let sub s to ctory face for
act Fa r
Abstr es an inte s of
extension but closed for s
modification.! object which cla ory
Providng familie ent
e t
decid tiate. Fac ss defer
n
Depend on abstractions. Do not insta d lets a cla the creati or depend
depend on concrete classes.! Metho tiation to d
relate without crete
n
insta sses.!
a o b j e ct s
g t h eir con
subcl yi n
specif s.!
classe

FEUP ● Nuno Flores ●


80

40
9/22/11

Challenge    
 The  Portuguese  style  pizza  usually  takes  
• stuffed  dough  
• cream  sauce  
• fresh  cheese  
• fresh  clams  
• Artichoke  and  black  olives  

 Add  the  respective  ingredient  factory  so  that  the  Portuguese  


pizza  store  can  get  the  quality  ingredients  its  needs.  
 factory.pizzaaf  

FEUP ● Nuno Flores ●


81

It  can’t  be  simpler  than  SINGLETON…  


 “There  can  be  ONE,  and  ONLY  ONE  instance”.  
• Thread  pools,    
• caches,    
• dialog  boxes,    
• Preferences  objecyts,  
•  registry  settings,  
•  logging,    
• device  drivers,  etc…  

 Instead  of  accessing  a  globla  variable,  control  instance  


creation  
• Create  only  when  needed,  to  spare  resources  (usually).  

FEUP ● Nuno Flores ●


82

41
9/22/11

Classic  SINGLETON  pattern  implementation  

public class Singleton { We have a static variable to


private static Singleton uniqueInstance;
Our constructor is
hold our one instance of the
class Singleton
declared private; only
Singleton can instantiate // other useful instance variables here
this class!

private Singleton() {} The getInstance() method gives us the


ONLY WAY to instantiate the class and
public static Singleton getInstance() { also to return an instance of it.
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
} The instance is only created if
return uniqueInstance; the static variable is null (one
} time) and later returned.
“Lazy instantiation”

// other useful methods here


} Of course, Singleton is a
normal class, therefore has
other variables and methods.

FEUP ● Nuno Flores ●


83

SINGLETON  pattern  defined…   nsure


on - Eas one
 Only  one  instance   nglet
Si ss only h ovide
a cla r
• Single  instance  managed  by  class  itself.   and p
nce
insta al point of
• Preventing  other  classes  from  creating  an   a gl b to it.!
o
instance  on  its  own.   access
• To  get  the  instance,  you  have  to  go  through  the  
class  itself  

 Global  access  point  


• When  you  want  an  instance  (the  ONE  instance),  
just  query  the  class  and  it  will  give  you.  

 Lazy  instantiation  
• Important  for  resource  intensive  objects.  

FEUP ● Nuno Flores ●


84

42
9/22/11

Not  all  is  well  with  SINGLETON…  


 What  happens  here?  
Thread Thread Value of
One Two unique instance
public static MySingleton
getinstance() { null

public static MySingleton null


getinstance() {

if (uniqueInstance == null) {
null
if (uniqueInstance == null) {
uniqueInstance =
new MySingleton(); <object1>
return uniqueInstance; <object1>

uniqueInstance = <object2>
new MySingleton();
<object2>
return uniqueInstance;
OOPSSS!!!

FEUP ● Nuno Flores ●


85

Dealing  with  multithreading  


 Making  getInstance()  a  syncronized  method  
public class Singleton {
private static Singleton uniqueInstance;

// other useful instance variables here


Every thread has to wait its turn before it
can enter the method. No two thread may
private Singleton() {} enter the method at the same time.

public static syncronized Singleton getInstance() {


if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}

// other useful methods here


}

 But  syncronization  is  expensive…  


• Only  relevant  in  the  first  time.  
• After  uniqueVariable  is  created,  syncronization  is  no  longer  needed.  

FEUP ● Nuno Flores ●


86

43
9/22/11

Improving  multithreading…  
 We  have  a  few  options  
1. Do  nothing  if  the  performance  isn’t  critical  to  your  application.  
2. Move  to  an  eagerly  created  instance  rather  than  a  lazily  created  one.  
public class Singleton {
private static Singleton uniqueInstance = new Singleton();

private Singleton() {}

public static Singleton getInstance() {


return uniqueInstance;
}
}
3. Use  “double-­‐checked  locking”  to  reduce  the  use  of  syncronization  in  
getInstance()  
public class Singleton {
private volatile static Singleton uniqueInstance;

// other useful instance variables here


The volatile keyword ensures
multiple threads handle the private Singleton() {}
uniqueInstance variable
correctly when it is being public static Singleton getInstance() {
initialized to the Singleton if (uniqueInstance == null) {
instance
syncronized (Singleton.class) {
if (uniqueInstance == null) { Enter a syncronized block
uniqueInstance = new Singleton(); only when creating the
} uniqueInstance
}
}
return uniqueInstance;
} FEUP ● Nuno Flores ●
87
}

Design  Billboard   Facto


ry -
tracat interface fo
r
OO Ba
sics!
a fam Abs
ily
efines psulatesrovide n s of Abstr
gy - d ca P milie action
Strate orithms, enakes them ating fa endent !
of alg e, and m Stttraach tegycre ted or dep Encap
OO Principles! ea ch on r
bl-e.A
agto hm vary nts jects wM
ea re la h ou t d - crete
it etho r conr sulatio
hoarne-
econ n!
tea
rc
efininesD thdeitaiolgnorait
l cliea ob ry g theiace fo Polym
ver - d letsacy d denibtlilyitfrieom s to n Fascpto ecifyaininterf ct but let orphis
Obsearny dependsen astpen
dep onit s ic ally.Defibinleesn
es .!na obje h m !
ointh
re .! n a m ex
c la
vide flcreatig
s n g e whic Inherit
n obto-m jects that u
nje ts rs pro gse
es dy
ct . decid
Encapsulate what varies.! betwee e object ch
aob
enato
in es
bclassusbclassinstantiate a ance!
on epen dor
Dec e to su to ts
when all of its d upadltaer tendativ g
in class y Method le tiation
te , d d n
Favor composition over inheritance.! satare notified llany.! for exctteionnality.! Factor efer insta .!
d
atica fun class subclasses
autom to the
Program to interfaces, not
implementations.!
Strive for loosely coupled
designs between object that
interact.!
n sure
ton - Eas one
Classes should be open for
extension but closed for
S ingle h
modification.!
s only ovide
a clas ce and pr
n
Depend on abstractions. Do not
depend on concrete classes.! insta al point of
g lo b
a to it.!
access

FEUP ● Nuno Flores ●


88

44
9/22/11

Remote  Control   There are “on” and


“off” button for each of
the slots

OFF These two buttons are


ON
used to control device
stored in slot one...

Seven different slots.


We can put a different
device in each slot … and these two control
and control it via the the device stored in slot
buttons two...

...and so on.

UNDO

Here’s the global “undo”


button that undoes the last
button pressed.
FEUP ● Nuno Flores ●
89

Remote  Control  
 Vendor  classes  to  control  
FaucetControl
CeilingLight ApplianceControl
TV openValue()
on() closeValue() on()
off() on() off()
Outdoor Light dim() off()
setInputChannel()
on() setVolume() Termostat
off() CeilingFan setTemperature() Stereo
high() GarageDoor on()
GardenLight medium() Hottub off()
up()
low() setCD()
down()
setDuskTime() off() circulate() setDVD()
stop()
setDawnTime() getSpeed() jetsOn() setRadio()
lightOn()
manualOn() jetsOff() setVolume()
lightOff()
manualOff() setTemperature()
Sprinkler
waterOn() SecurityControl Light
waterOff()
arm() on()
disarm() off()

 Ok,  talking  about  Uncommon  interfaces…  

FEUP ● Nuno Flores ●


90

45
9/22/11

Design  concerns  
 Separation  of  concerns.  
• The  remote  should  know  how  to  interpret  button  presses  and  make  
requests.  
• The  remote  should  not  know  a  lot  about  house  automation.  
-­‐ How  to  turn  on  a  hot  tub,  how  to  dim  the  lights,  etc…  

 We  don’t  want  to  know  the  specifics  of  the  vendor  classes.  
• IF  slot1  ==  Light  THEN  light.on()  =  BAD  DESIGN!!!  
• In  the  future  we  can  expect  more  vendor  classes  with  more  diverse  
methods.  

 We  want  to  decouple  the  requester  of  an  action  from  the  
object  that  actually  performs  the  action.  
• “requester”  :  the  remote  control.  
• “action  performer”  :  an  instance  of  one  of  the  vendor  classes.  

FEUP ● Nuno Flores ●


91

A  brief  introduction  to  the  COMMAND  pattern…  

 The  Diner  example  


The Customer give the ER The Waitress takes the
1 O RD
Waitress her Order ur 2 Order, places it on the order
Yo s eb
hee s
lec frie counter and says “Order up!”
oub with ies
D er gg
urg d ve
an

The Short-Order Cook prepares


3
the meal from the Order

FEUP ● Nuno Flores ●


92

46
9/22/11

A  brief  introduction  to  the  COMMAND  pattern…  

 Let’s  study  the  interaction  in  a  little  more  detail…  


ER
O RD
ur
Yo seb createOrder()
hee s
lec th frie
ub
takeOrder() Do er wi ggies
urg d ve
an

The order consists of an order


slip and the customer’s menu
items that are written on it. The customer knows
what he wants and
Do other They are decoupled by an Order Slip creates an order
chores...
The Waitress takes the Order, and when
she gets around to it, she calls its orderUp()
method to begin the Order’s preparation

orderUp()
RD
ER makeBurger(), makeFries()
O
ur
Yo seb output
hee s
lec h frie
ub
Do er wit ggies
urg d ve
The Order has all the instructions a n

neeced to prepare the meal. The


Order directs the Short-Order Cook
with methods like makeBurger()

FEUP ● Nuno Flores ●


93

From  the  Diner  to  the  COMMAND  pattern…  


publ
ic v
rece oid ex
i e
r e c e v e r. a c c u t e ( )
} iver ti {
.act on1(); Receiver
ion 2 1
(); execute()
createCommandObject( )
re
t he
Command Star
2
createCommandObject()
setCommand()

3
Client

later asks to
execute command
action1()
action2()
setCommand() ...

Receiver
Invoker action1(), action2()
execute() execute()

Command

FEUP ● Nuno Flores ●


94

47
9/22/11

From  theory  to  practice…  


 Implementing  the  command  interface  
public interface Command {
public void execute();
}
 Implementing  a  Command  to  turn  a  light  on  
public class LightOnCommand implements Command { Light
Light light; on()
off()
public LightOnCommand(Light light) {
this.light = light;
} In constructor is passed
the specific light to
control. This is the
public void execute() { Receiver on execute().
light.on();
} The execute() method
} calls the on() method on
the receiving object, in
this case, the light.

FEUP ● Nuno Flores ●


95

From  theory  to  practice…  


 Using  the  command  object  
We have one slot to hold
public class SimpleRemoteControl { our command, which will
Command slot; control one device

public SimpleRemoteControl() {}
Method for setting the command in
public void setCommand(Command command) { the slot. Could be called multiple
slot = command; times to change the behaviour of
the remote button
}

public void buttonWasPressed() {


slot.execute(); Method called when button pressed.
Calls the execute() of the command in
} the slot.
}
This is our “Client”
 Simple  test  to  use  the  Remote  Control  
The remote is our invoker, it will
public class RemoteControlTest { be passed a command object that
can be used to make requests
public static void main(String[] args) {

SimpleRemoteControl remote = new SimpleRemoteControl();


Create a light to be the receiver of the
Light light = new Light(); request.
LightOnCommand lightOn = new LightOnCommand(light);

remote.setCommand(lightOn); Here, create a command


and pass it to the receiver
remote.buttonWasPressed();
}
} Here, pass the command to
the invoker.
Simulate a button FEUP ● Nuno Flores ●
being pressed 96

48
9/22/11

GarageDoor

Without  looking…   up()


down()
stop()
lightOn()
 Implement  the  GarageDoorOpenCommand   lightOff()

public class GarageDoorOpenCommand implements Command {


GarageDoor garageDoor;

public GarageDoorOpenCommand(GarageDoor garageDoor) {


this.garageDoor = garageDoor;
}

public void execute() {


garageDoor.up();
}
}

 Here’s  the  test  code…  


public class RemoteControlTest {
public static void main(String[] args) {

SimpleRemoteControl remote = new SimpleRemoteControl();

GarageDoor garageDoor = new GarageDoor();


GarageDoorOpenCommand garageOpen = new GarageDoorOpenCommand(garageDoor);

remote.setCommand(garageOpen);
remote.buttonWasPressed();
}
}

FEUP ● Nuno Flores ●


97

The  COMMAND  pattern  defined…  


ulates
 Allow  decoupling  between  a  requester   E ncaps
and -an object,
and  a  receiver.   Comm s est a ou
a requy letting y nts with
r
• Encapsulates  requests  as  objects  with   there eterize clie s, queue o
b
t
common  interface.   parament reques support
d
differ uests, an ons.!
o g r e q e r at i
• Allow  for  parameterization  of  requests  on   l
able o
p
undo
an  invoker.  
The Invoker holds a command and at some
point asks the command to carry out a
The Client is responsible for request by calling its execute() method
creating a ConcreteCommand
Command declares and
and setting its Receiver
interface for all commands.

The execute method invokes


the action(s) on the receiver
needed to fulfill the request

The ConcreteCommand defines a binding


The Receiver knows how to perform the between an action and a Receiver. Used
work needed to carry out the request. Any by the Invoker to carry out its requests.
class can act as a Receiver.
FEUP ● Nuno Flores ●
98

49
9/22/11

Back  to  the  Remote  Control…  


(2) When the button is pressed, the execute()
method is called on the corresponding command.
(1) Each slot gets a command.

LightOffCommand
OFF
LightOnCommand ON

LightOffCommand

LightOnCommand

CeilingFanOff

CeilingFanHigh

GarageDoorClose

GarageDoorOpen

StereoOff
StereoOnForCD

(3) In the execute() method actions


are invoked on the receiver.
UNDO

on()
off()

The Invoker
Stereo FEUP ● Nuno Flores ●
99

Implementing  the  Remote  Control  


public class RemoteControl {
Command[] onCommands;
Command[] offCommands;

public RemoteControl() { Command storage


onCommands = new Command[7]; structure initialization.
offCommands = new Command[7];

Command noCommand = new NoCommand();


for (int i = 0; i < 7; i++) {
onCommands[i] = noCommand;
offCommands[i] = noCommand; This is called a NULL
} OBJECT pattern. More on
this later...
}

public void setCommand(int slot, Command onCommand, Command offCommand) {


onCommands[slot] = onCommand;
offCommands[slot] = offCommand;
}

public void onButtonWasPushed(int slot) {


onCommands[slot].execute();
} When on or off buttons are pressed, it
invokes the execute() on the command
public void offButtonWasPushed(int slot) { object stored in the respective slot.
offCommands[slot].execute();
}

public String toString() {


// pretty printing code here . . .
}
}

FEUP ● Nuno Flores ●


100

50
9/22/11

Implementing  the  Commands  


public class LightOffCommand implements Command {
Light light;

public LightOffCommand(Light light) {


this.light = light;
}

public void execute() {


light.off();
}
}

public class StereoOnWithCDCommand implements Command {


Stereo stereo;

public StereoOnWithCDCommand(Stereo stereo) {


this.stereo = stereo;
}

public void execute() { Stereo


stereo.on(); on()
stereo.setCD(); off()
stereo.setVolume(11); setCD()
} setDVD()
} setRadio()
setVolume()

FEUP ● Nuno Flores ●


101

What  with  that  NoCommand  thing?  


 We  didn’t  want  to  check  to  see  if  a  command  was  loaded  
everytime  we  referenced  a  slot.  
public void onButtonWasPushed(int slot) {
if (onCommands[slot] != null) {
onCommands[slot].execute();
}
}

 How  to  get  around  this?    


• Implement  a  command  that  does  nothing!   moves
t - Re f
Objec
public class NoCommand implements Command { Null nsability o from the
public void execute() { } respo ng nulls is no
li
hand when there ult. !
} client gfull res
in
mean

 Remote  Control  slots  initialized  by  default  with  a  


NoCommand  command  
Command noCommand = new NoCommand();
for (int i = 0; i < 7; i++) {
onCommands[i] = noCommand;
offCommands[i] = noCommand;
}
FEUP ● Nuno Flores ●
102

51
9/22/11

UNDO  button  missing…  


 Adding  undo()  to  Command…  
public interface Command {
public void execute();
public void undo();
}

 …  and  ConcreteCommand.  
public class LightOnCommand implements Command {
Light light;

public LightOnCommand(Light light) {


this.light = light;
}

public void execute() {


light.on();
}
public void undo() {
light.off();
}
}

FEUP ● Nuno Flores ●


103

…  but  now  it  works!  


public class RemoteControlWithUndo {
Command[] onCommands;
Command[] offCommands;
Command undoCommand;

public RemoteControlWithUndo() {
onCommands = new Command[7];
offCommands = new Command[7];

Command noCommand = new NoCommand();


for(int i=0;i<7;i++) {
onCommands[i] = noCommand;
offCommands[i] = noCommand;
}
undoCommand = noCommand;
}

public void setCommand(int slot, Command onCommand, Command offCommand) {


onCommands[slot] = onCommand;
offCommands[slot] = offCommand;
}

public void onButtonWasPushed(int slot) {


onCommands[slot].execute();
undoCommand = onCommands[slot];
}

public void offButtonWasPushed(int slot) {


offCommands[slot].execute();
undoCommand = offCommands[slot];
}

public void undoButtonWasPushed() {


undoCommand.undo();
}
. . . FEUP ● Nuno Flores ●
104

52
9/22/11

Using  state  to  implement  Undo  


public class CeilingFan {
public static final int HIGH = 3;
public static final int MEDIUM = 2;
public static final int LOW = 1;
Notice that the CeilingFan holds
public static final int OFF = 0; local state representing the speed
String location; of the ceiling fan.
int speed;

public CeilingFan(String location) {


this.location = location;
speed = OFF;
}

public void high() {


speed = HIGH;
// code to set fan to high
}

public void medium() {


speed = MEDIUM;
// code to set fan to medium Methods that set the fan speed
}

public void low() {


speed = LOW;
// code to set fan to low
}

public void off() {


speed = OFF;
// code to turn fan off
}

public int getSpeed() { Speed getter


return speed;
}
FEUP ● Nuno Flores ●
} 105

Addind  Undo  to  the  ceiling  fan  commands  


public class CeilingFanHighCommand implements Command {
CeilingFan ceilingFan;
int prevSpeed; Added local state tracking

public CeilingFanHighCommand(CeilingFan ceilingFan) {


this.ceilingFan = ceilingFan;
}

public void execute() {


prevSpeed = ceilingFan.getSpeed(); We store current fan speed
ceilingFan.high(); before changing it.
}

public void undo() {


if (prevSpeed == CeilingFan.HIGH) {
ceilingFan.high();
} else if (prevSpeed == CeilingFan.MEDIUM) { We undo to the
ceilingFan.medium(); previous fan speed
} else if (prevSpeed == CeilingFan.LOW) {
ceilingFan.low();
} else if (prevSpeed == CeilingFan.OFF) {
ceilingFan.off();
}
}
}

FEUP ● Nuno Flores ●


106

53
9/22/11

Using  a  macro  command  


 Every  remote  needs  a  Party  Mode!  
• Create  a  new  kind  of  Command  that  execute  more  than  one  
Command,  that  is,  several  Commands.  
public class MacroCommand implements Command {

Command[] commands;

public MacroCommand(Command[] commands) {


this.commands = commands;
}

public void execute() {


for (int i = 0; i < commands.length; i++) {
commands[i].execute();
}
}

public void undo() {


for (int i = 0; i < commands.length; i++) {
commands[i].undo();
}
}
}

FEUP ● Nuno Flores ●


107

Using  a  macro  command  


public class RemoteLoader {

public static void main(String[] args) {

RemoteControl remoteControl = new RemoteControl();


Creating RemoteControl
(Invoker)
Light light = new Light("Living Room");
TV tv = new TV("Living Room");
Stereo stereo = new Stereo("Living Room");
Creating Receivers
Hottub hottub = new Hottub();

LightOnCommand lightOn = new LightOnCommand(light);


StereoOnCommand stereoOn = new StereoOnCommand(stereo);
TVOnCommand tvOn = new TVOnCommand(tv);
HottubOnCommand hottubOn = new HottubOnCommand(hottub);
LightOffCommand lightOff = new LightOffCommand(light);
Creating Commands
StereoOffCommand stereoOff = new StereoOffCommand(stereo);
TVOffCommand tvOff = new TVOffCommand(tv);
HottubOffCommand hottubOff = new HottubOffCommand(hottub);

Command[] partyOn = { lightOn, stereoOn, tvOn, hottubOn};


Creating Command arrays
Command[] partyOff = { lightOff, stereoOff, tvOff, hottubOff};

MacroCommand partyOnMacro = new MacroCommand(partyOn);


MacroCommand partyOffMacro = new MacroCommand(partyOff);
Creating command Macros
remoteControl.setCommand(0, partyOnMacro, partyOffMacro);
Setting party button slot on
RemoteControl
System.out.println(remoteControl);
System.out.println("--- Pushing Macro On---");
remoteControl.onButtonWasPushed(0);
Pushing party button... System.out.println("--- Pushing Macro Off---");
remoteControl.offButtonWasPushed(0);
}
}
FEUP ● Nuno Flores ●
108

54
9/22/11

Other  uses  for  COMMAND  pattern  


 Queueing  requests  
• Command  objects  are  queued  and  scheduled  for  later  execution.  
• Thread  pools,  job  queues,  schedulers,  etc…  

 Logging  requests  
<<interface>> • Log  actions  to  be  able  to  recover  from  a  crash.  
Command
execute() • As  we  execute  commands,  we  store  them  in  a  history  on  disk.  
undo()
load() • When  a  crash  occurs,  we  reload  the  command  objects  and  invoke  
store()
their  execute()  methods  in  batch  and  in  order.  
• Ex:  database  processes,  large  data  handling,  communications,  etc…  

FEUP ● Nuno Flores ●


109

Design  Billboard   Facto


ry -
tracat interface fo
r
OO Ba
sics!
a fam Abs
ily
efines psulatesrovide n s of Abstr
gy - d ca P milie action
Strate orithms, enakes them ating fa endent !
of alg e, and m Stttraach tegycre ted or dep Encap
OO Principles! ea ch on r
bl-e.A
agto hm vary nts jects wM
ea re la h ou t d - crete
it etho r conr sulatio
hoarne-
econ n!
tea
rc
efininesD thdeitaiolgnorait
l cliea ob ry g theiace fo Polym
ver - d letsacy d denibtlilyitfrieom s to n Fascpto ecifyaininterf ct but let orphis
Obsearny dependsen astpen
dep onit s ic ally.Defibinleesn
es .!na obje h m !
ointh
re .! n a m ex
c la
vide flcreatig
s n g e whic Inherit
to-m n ob jects that u gse
es dy
ct
nje ts rs pro . decid
Encapsulate what varies.! betwee e object ch
aob
enato
in es
bclassusbclassinstantiate a ance!
on Dec
epen dor e to su to ts
when all of its d upadltaaer tendativ g
in class y Method le tiation
te , d re d n
Favor composition over ied- aEnnsu for extennality.!
inheritance.! satare lneottoifn Factor efer insta .!
d
ye.! class subclasses
Sinsaguon toly s ll
mahtiaca on
e fu
a
nctio
to the
Program to interfaces, not s cla provid
nd ccess to
nce a
implementations.! insta l point of a
globa
Strive for loosely coupled it.!
designs between object that
interact.!
s ulates
Encap
Classes should be open for nd - object,
extension but closed for C omma an
est as ou
modification.! a requy letting y nts with
th e r e b
eteriz
e c l i e eue or
Depend on abstractions. Do not ts, qu
depend on concrete classes.! parament reques support
d
differ uests, an ons.!
q
log re ble operati
a
undo

FEUP ● Nuno Flores ●


110

55
9/22/11

Quick  Challenge    
 Implement  a  MacroCommand  that,  besides  setting  a  Party,  
also  turns  on  the  house  outside  lights,the  garden’s  sprinkler  
system  and  opens  the  living  room  windows.  Dont’  forget  
“undo”.  
 Give  it  a  testing  try…  
 Check  the  rest  of  the  code,  just  for  the  record…  

FEUP ● Nuno Flores ●


111

Object  oriented  adapters  


 Surely  this  should  have  happened  to  you…  

 Adapter  concepts  
• Unmatching  interfaces:  same  purpose,  different  publishing…  

Your
Vendor
Existing
Class
System
Adapter New code
Your
Vendor
Existing No code changes
Class No code changes
Their interface doesn’t match the System
one you’ve written your code
against! This isn’t going to work!

The adapter implements the Adapter


Your
interface your classes expect. Vendor
Existing
Class
And talks to the vendor interface to System
service your requests.

FEUP ● Nuno Flores ●


112

56
9/22/11

A  turkey  pretends  to  be  a  duck…  


 We  have  our  Ducks…  
public interface Duck {
public void quack();
public void fly();
} public class MallardDuck implements Duck {
public void quack() {
System.out.println("Quack");
}

public void fly() {


System.out.println("I'm flying");
}
}

 and  a  turkey…  
public interface Turkey {
public void gobble();
public void fly();
}
public class WildTurkey implements Turkey {
public void gobble() {
System.out.println("Gobble gobble");
}

public void fly() {


System.out.println("I'm flying a short distance");
}
} FEUP ● Nuno Flores ●
113

And  so  turkeys  adapt…  

You need to implement the interface of


the type you’re adapting to. This is the
interface your client expects to see

public class TurkeyAdapter implements Duck {


Turkey turkey;

public TurkeyAdapter(Turkey turkey) { We need to get a reference to the


this.turkey = turkey; object that we are adapting; we do
} that through the constructor.

public void quack() { We need to implement all the methods


turkey.gobble(); in the interface: the quack() translation
between classes is easy: just call the
} gobble() method

public void fly() {


for(int i=0; i < 5; i++) {
turkey.fly();
}
} Both interfaces have a fly() method,
} but turkeys fly in small bursts. To
map between the two we need to
call turkey’s fly at least five times.

Can you write a DuckAdapter?

FEUP ● Nuno Flores ●


114

57
9/22/11

ADAPTER  pattern  defined   onver


ts the
o
Adaptee ter - C ss int
Client Adap ce of a cla clients
a e
request() interf er interfac es work
anoth . Lets class dn’t
translatedRequest()

l
expect er that cou of
e
togeth ise becaus erfaces.!
adaptee interface Adapter otherw patible int
incom
target interface

All requests are delegated to


the Adaptee

The client sees only the


target interface
Adapter is composed
with the Adaptee

The Adapter implements


the target interface

Footnote: There is also a solution using multiple ihneritance.


FEUP ● Nuno Flores ●
115

Real  world  adapters  


 Adapting  an  Enumeration  to  an  Iterator  
These two methods look easy,
they map straight to hasNext()
and next() in Iterator
Target interface

<<interface>> <<interface>>
Iterator Enumerator
hasNext() hasMoreElements()
next() nextElement()
remove()
Adaptee interface

But what about this method


remove() in Iterator? There’s
nothing like that in Enumeration?

Your new code still gets to use


<<interface>>
Iterators, even if there’s really na Iterator
Enumeration underneath
hasNext() We’re making the Enumerations in
next() your old code look like Iterators for
remove()
your new code.

Adaptee
EnumerationIterator <<interface>>
Enumerator
hasNext()
next() hasMoreElements()
Adapter remove() nextElement()

FEUP ● Nuno Flores ●


116

58
9/22/11

Real  world  adapters  


 Writing  the  EnumerationIterator  adapter…  
• …and  also  dealing  with  the  remove()  method.  
public class EnumerationIterator implements Iterator {
Enumeration enumeration;

public EnumerationIterator(Enumeration enumeration) {


this.enumeration = enumeration;
}

public boolean hasNext() {


return enumeration.hasMoreElements();
}

public Object next() {


return enumeration.nextElement();
}

public void remove() {


throw new UnsupportedOperationException();
}
}

 Make  an  IteratorEnumerator  adapter.  


FEUP ● Nuno Flores ●
117

Challenge    
 Try  to  make  a  Chicken  look  like  a  Duck  
Chicken
• It  cackles.  
cackle()
• When  trying  to  fly,  it  flaps  and  falls.   flapWings()
fall()
 Can  a  Duck  look  like  a  Chicken?  

FEUP ● Nuno Flores ●


118

59
9/22/11

And  now  for  something  completely  different…  

 Home  Sweet  Home  Theater  


That’s a lot of classes, a lot of
interactions, and a big set of
Amplifier interfaces to learn and use.

tuner
dvdPlayer
cdPlayer
Tuner
on()
amplifier DvdPlayer
off()
on() setCD()
off() setDVD() amplifier
setAM() setStereoSound()
on()
setFM() setSurroundSound()
off()
setFrequency() setTuner()
eject()
setVolume()
pause()
play()
Screen setSurroundAudio()
up() setTwoChannelAudio()
CdPlayer stop()
down()
amplifier

TheaterLights on() Projector


off()
PopcornPopper on() eject() dvdPlayer
off() pause()
on() dim() play() on()
off() stop() off()
pop() tvMode()
wideScreenMode()

FEUP ● Nuno Flores ●


119

Watching  a  movie  (the  hard  way)  


 Just  have  to  do  a  “few”  things…    How  do  it  go  in  terms  of  classes…  
1. Turn  on  the  popcorn  popper   popper.on();
2. Start  the  popper  popping   popper.pop();
3. Dim  the  lights   lights.dim(10);
4. Put  the  screen  down  
screen.down();
5. Turn  the  projector  on  
6. Set  the  projector  input  to  DVD   projector.on();
7. Put  the  projector  on  wide-­‐screen   projector.setInput(dvd);
projector.wideScreenMode();
mode  
8. Turn  the  sound  amplifier  to  DVD   amp.on();
input     amp.setDvd();
amp.setSurroundSound();
9. Set  the  amplifier  to  DVD  input   amp.setVolume(5);
10. Set  the  amplifier  volume  to  medium  
(5)   dvd.on();
dvd.play(movie);
11. Turn  the  DVD  Player  on  
12. Start  the  DVD  Player  playing.  

• Puf,  Puf,  Puf!!!!    At  the  end,  you  have  to  turn  


everything  off:  do  the  reverse!  

FEUP ● Nuno Flores ●


120

60
9/22/11

Lights,  Camera,  FACADE!  


The Facade
watchMovie()
The subsystem
the Facade is
simplifying
A client of the facade
HomeTheaterFacade

watchMovie()
endMovie()
listenToCD()
endCD()
listenToRadio()
endRadio()

Amplifier

tuner
dvdPlayer
cdPlayer
Tuner
on()
amplifier off()
DvdPlayer
setCD()
on()
setDVD() amplifier
off() setStereoSound()
setAM() setSurroundSound() on()
setFM() setTuner() off()
setFrequency()
setVolume() eject()
pause()
play()
Screen setSurroundAudio()
up() setTwoChannelAudio()
CdPlayer stop()
down()
amplifier

TheaterLights on() Projector


The subsytem is still off()
accessible directly PopcornPopper on() eject() dvdPlayer
off() pause()
on() dim() play() on()
off() stop() off()
pop() tvMode()
wideScreenMode()

FEUP ● Nuno Flores ●


121

Constructiong  your  home  theatre  facade  


public class HomeTheaterFacade {
Amplifier amp;
Tuner tuner;
DvdPlayer dvd;
CdPlayer cd;
Projector projector;
TheaterLights lights;
Screen screen;
PopcornPopper popper;

public HomeTheaterFacade(Amplifier amp,


Tuner tuner,
DvdPlayer dvd,
CdPlayer cd,
Projector projector,
Screen screen,
TheaterLights lights,
PopcornPopper popper) {

this.amp = amp;
this.tuner = tuner;
this.dvd = dvd;
this.cd = cd;
this.projector = projector;
this.screen = screen;
this.lights = lights;
this.popper = popper;
}
. . .
FEUP ● Nuno Flores ●
122

61
9/22/11

Implementing  the  simplified  interface  


public void watchMovie(String movie) {
System.out.println("Get ready to watch a movie...");
popper.on();
popper.pop();
lights.dim(10);
screen.down();
projector.on();
projector.wideScreenMode();
amp.on();
amp.setDvd(dvd);
amp.setSurroundSound();
amp.setVolume(5);
dvd.on();
dvd.play(movie);
}

public void endMovie() {


System.out.println("Shutting movie theater down...");
popper.off();
lights.on();
screen.up();
projector.off();
amp.off();
dvd.stop();
dvd.eject();
dvd.off();
}

FEUP ● Nuno Flores ●


123

Time  to  watch  a  movie  (the  easy  way)  

public class HomeTheaterTestDrive {

public static void main(String[] args) {

Amplifier amp = new Amplifier("Top-O-Line Amplifier");


Tuner tuner = new Tuner("Top-O-Line AM/FM Tuner", amp);
DvdPlayer dvd = new DvdPlayer("Top-O-Line DVD Player", amp);
CdPlayer cd = new CdPlayer("Top-O-Line CD Player", amp);
Projector projector = new Projector("Top-O-Line Projector", dvd);
TheaterLights lights = new TheaterLights("Theater Ceiling Lights");
Screen screen = new Screen("Theater Screen");
PopcornPopper popper = new PopcornPopper("Popcorn Popper");

HomeTheaterFacade homeTheater =
new HomeTheaterFacade(amp, tuner, dvd, cd,
projector, screen, lights, popper);

homeTheater.watchMovie("Raiders of the Lost Ark");


homeTheater.endMovie();
}
}

FEUP ● Nuno Flores ●


124

62
9/22/11

FACADE  pattern  defined   rovide


sa
set
e - P rface to a
 Not  only  simplifies  na  interface,  it  decouples  a   Facad e d te
i n a
unifi erfaces in de
cilent  from  a  subsystem  of  components.   of int stem. Faca level
subsy s a higher- kes the
 Facade  vs  Adapter   e a
defin ace that m r to use.!
• Both  wrap  multiple  classes   interf stem easie
subsy
• Facade’s  intent:  simplify  an  interface.  
• Adapter’  intent:  convert  na  interface  to  something  
different.  

FEUP ● Nuno Flores ●


125

Principle  of  Least  Knowledge   “Talk


PLK -to your
 Beware  of  how  many  classes  an  object  interact  with.   only diate
imme s”.!
• Try  to  minimize  the  dependencies  between  classes.  
friend
• Strive  for  decoupling  whenever  possible.  

 How  many  classes  is  this  code  coupled  to?  


public float getTemp() {
return station.getThermometer().getTemperature();
}

 Guidelines  
• Given  any  object,  only  invoke  methods  that  belong  to:  
-­‐ The  object  itself  
-­‐ Objects  passed  in  as  a  parameter  to  the  method  
-­‐ Any  object  the  method  creates  or  instantiates  
-­‐ Any  components  of  the  object  (HAS-­‐A  relationship)  
public float getTemp() {
 Without  the  principle   Thermometer t = station.getThermometer();
return t.getTemperature();
}
public float getTemp() { Like this we dont’ have to get
 With  the  principle   station.getTemperature(); Thermometer object to get the
temperature.
}

FEUP ● Nuno Flores ●


126

63
9/22/11

A  more  complete  example  of  PLK  


public class Car {
Here’s a component of this class.
Engine engine; We can still call its methods.
// other instance variables

public Car() {
// initialize engine, etc…
}
Here we’re creating a new object,
its methods are legal.
public void start(Key key) {
Doors doors = new Doors(); You can call a method on an object
passed as a parameter

boolean authorized = key.turns();


You can call a method on a
if (authorized) { component of the object
engine.start();
updateDashboardDisplay(); You can call a local method within
doors.lock(); the object
} You can call a method on an
} object you create or instantiate

public void updateDashboardDisplay() {


// update display
}
}

FEUP ● Nuno Flores ●


127

Check  these  out  


 Do  you  see  any  principle  violations?  
public class House {
WeatherStation station;

// other methods and constructors

public float getTemp() {


return station.getThermometer().getTemperature();
}
}
public class House {
WeatherStation station;

// other methods and constructors

public float getTemp() {


Thermometer t = station.getThermometer();
return getTempHelper(t);
}

public float getTempHelper(Thermometer t) {


return t.getTemperature();
}
}
 Can  you  think  of  a  common  use  of  Java  that  violates  this  principle?  

FEUP ● Nuno Flores ●


128

64
9/22/11

Design  Billboard   ily bstrac


ory -
t Fact for ace
OO Ba
sics!
a fam teA interf Abstr
efines
gy - d s, encapsu emProv
la s ide na milies of action
S tr a te
orithm kes th gycreatin
g fa dent !
OO Principles! of alg e, and ma Stttraach depen Encap
te
earbl-e.A vary rela
ted or hout - crete sulatio
each onon a
e-gto w it th o d onr
ec
tea
rc hoarn
l hm clnieants
ts
objec ry Mg theiarcecfo
e n!
efininesD thdeitaiolgnorait s to Fascpto Polym
ver - d letsacy d denibtlilyitfrieom ecifyaininterf ct but let orphis
Obsearny dependsen thd ep
asten
p on s ic a ll y.Definleesn
ib s es.!
n a ob je ich m!
o ret use itdynam ide wh
in .!
to-m n objects thaaob e flexclatigng Inherit
Encapsulate what varies.! ch nje
es
gct provid crsea sin sses dec ate. ance!
betwee e object epen dor
Dec
tors
enats
e to su
bclasubcla instanti
ts a
on to
when all of its d upadltaaer tendativ g class y Method le tiation
Favor composition over inheritance.! state, ified- aEnndsurefor extendin .! Factor efer insta .!
n
l
n e t
ot o n .! n a lity s d es
Sinaaguon
re oney io s s s
mahtiacas ll funct psulates cla subcla
Program to interfaces, not
toly vide a- Enca to the
class ce andom pro and to object,
n C of um
insta l poinat re accesass na
implementations.! b a
q est ing you with
le tt nts
g lo y
ther eterize clie , queue or
eb
Strive for loosely coupled it.! param t requests pport
n su
differe uests, andons.!
designs between object that q
log re ble operati
a
vides
n doa
interact.! u
t
e
e - Pro to a s
Classes should be open for Facad interface
ed a
unifi erfaces in de
extension but closed for
modification.!
Depend on abstractions. Do not of int stem. Faca level
s the subsy s a higher- kes the
depend on concrete classes.!
C o nvert into e a
ter - ss defin ace that m r to use.!
Only talk to your friends.! Adap ace of a clae clients interf stem easie
n te r f e r f a c k
i er int es wor subsy
anoth . Lets class dn’t
l
expect er that cou of
g e t h a u s e .!
to
e r w i se be interfaces
c
oth pa t i b l e
incom
FEUP ● Nuno Flores ●
129

Time  for  break?  Coffee?  Tea?  

Recipe
eparation
Coffee Pr
me water
(1)Boil so iling wate
r
) Br ew co ffee in bo
(2 p
ffee in cu
(3)Pour co
lk
gar and mi
(4)Add su

pe
ation Reci
Tea Prepar
me wate r
(1)Boil so ing water
ep te a in boil
(2)Ste
a in cup
(3)Pour te
mon
(4)Add le

FEUP ● Nuno Flores ●


130

65
9/22/11

Whipping  up  some  coffee  and  tea  classes  


public class Coffee {

void prepareRecipe() {
boilWater();
brewCoffeeGrinds();
pourInCup();
addSugarAndMilk();
}
Here is the recipe for making the drink.
public void boilWater() { Each of the steps is implemented as a
System.out.println("Boiling water"); separate method.
}

public void brewCoffeeGrinds() {


System.out.println("Dripping Coffee through filter");
}
public class Tea {
public void pourInCup() {
System.out.println("Pouring into cup"); void prepareRecipe() {
}
boilWater();
steepTeaBag();
public void addSugarAndMilk() { pourInCup();
System.out.println("Adding Sugar and Milk");
addLemon();
} }
}
public void boilWater() {
System.out.println("Boiling water");
}

public void steepTeaBag() {


System.out.println("Steeping the tea");
}

public void addLemon() {


System.out.println("Adding Lemon");
}

public void pourInCup() {


System.out.println("Pouring into cup");
}
}
FEUP ● Nuno Flores ●
131

Sir,  may  I  abstract  your  Coffee,  Tea?  


The boilWater() and pourInCup()
methods are shared by both
The prepareRecipe() method subclasses, so they are defined in
CaffeineBeverage
differs in each subclass, so it the superclass.
is defined as abstract. prepareRecipe()
boilWater()
pourInCup()

Each subclass overrides the


Each subclass prepareRecipe() method and
implements its own implements its own recipe
recipe
Coffee Tea

prepareRecipe() prepareRecipe()
brewCoffeeGrinds() steepTeaBag()
addSugarAndMilk() addLemon()

The methods specific


to Coffee and Tea stay
in the subclasses

 Can  we  improve  this  design?  

FEUP ● Nuno Flores ●


132

66
9/22/11

Abstracting  prepareRecipe()  
Coffee Tea
void prepareRecipe() { void prepareRecipe() {
boilWater(); boilWater();
brewCoffeeGrinds(); brewCoffeeGrinds();
pourInCup(); pourInCup();
addSugarAndMilk(); addSugarAndMilk();
} }

void prepareRecipe() {
boilWater();
brew();
pourInCup(); {
public abstract class CaffeineBeverage
addCondiments();
It is declared final so that the }
subclasses can’t override it.
final void prepareRecipe() {
boilWater(); Now the same prepareRecipe()
brew(); method will be used to make
pourInCup(); both Tea and Coffee.
addCondiments();
}
Because Coffee and Tea handle these
abstract void brew(); methods in differrent ways, they’re going
to have to be declared as abstract. Let
the subclasses worry about that stuff!
abstract void addCondiments();

void boilWater() {
System.out.println("Boiling water");
}

void pourInCup() {
System.out.println("Pouring into cup");
}
} FEUP ● Nuno Flores ●
133

Implementing  the  subclasses…  


public class Tea extends CaffeineBeverage {

public void brew() {


System.out.println("Steeping the tea");
}

public void addCondiments() {


System.out.println("Adding Lemon");
}
}

public class Coffee extends CaffeineBeverage {

public void brew() {


System.out.println("Dripping Coffee through filter");
}

public void addCondiments() {


System.out.println("Adding Sugar and Milk");
}
}

 The  only  method  they  need  to  implement  are  the  abstract  
brew()  and  addCondiments()  

FEUP ● Nuno Flores ●


134

67
9/22/11

Meet  the  TEMPLATE  METHOD  pattern  


prepareRecipe() ir our template method.
Why?
public abstract class CaffeineBeverage { Because:

final void prepareRecipe() { (1) It is a method, after all

boilWater(); (2) It serves as a template for an


Some methods are
algorithm, in this case, an algorithm for
handled by the class...
making caffeinated beverages.
brew();

… and some methods are pourInCup(); In the template, each step of the
handled by the subclass. algorithm is represented by a
addCondiments(); method.

The methods that need to abstract void brew();


be supplied by a subclass
are declared abstract. abstract void addCondiments();

void boilWater() {
System.out.println("Boiling water");
}

void pourInCup() {
System.out.println("Pouring into cup");
}
}

FEUP ● Nuno Flores ●


135

TEMPLATE  METHOD  defined   Defin


e
od -
e Methan algorith
m
 The  TEMPLATE  METHOD  defines  the  steps  of   Te m p l a t f g
o in
eleton deferr
an  algorithm   the sk operation, classes.
an sub in asses to
steps subcl
• Allowing  subclasses  to  provide  the  implementation   some ate Methodsteps of an
l
for  one  or  more  steps.   Temp ne certain t
u
redefi thm witho orithm’s
i g
algor ing the al
chang ure.!
struct
The template method makes use of the
primitiveOperations to implement an
algorithm. it is decoupled from the actual
The AbstractClass implementation of these operations
contains the template
method.

...and abstract versions of


the operations used in the
template method

The ConcreteClass implements the


There may be many abstract operations, which are called
ConcreteClasses, each when the templateMethod() needs them.
implementing the full set of
operations required by the
template method. FEUP ● Nuno Flores ●
136

68
9/22/11

Hooking  the  template  method…  


 Hook  :  called  by  the  template  method  
• abstract  or  with  a  default  implementation,  always  overridable.  
public abstract class CaffeineBeverageWithHook {

void prepareRecipe() {
boilWater();
brew();
pourInCup();
if (customerWantsCondiments()) {
addCondiments();
}
}

abstract void brew();


Hooks
abstract void addCondiments();

void boilWater() {
System.out.println("Boiling water");
} Technically,
these are also
hooks, but ther is
void pourInCup() { no point in
System.out.println("Pouring into cup"); overriding them.
}
Subclasses may (or not)
boolean customerWantsCondiments() { override this one.
return true; They should whereas its
} default implementation is
} nearly empty
FEUP ● Nuno Flores ●
137

Using  the  hook  


public class CoffeeWithHook extends CaffeineBeverageWithHook {

public void brew() {


System.out.println("Dripping Coffee through filter");
}

public void addCondiments() {


System.out.println("Adding Sugar and Milk");
}

public boolean customerWantsCondiments() {

String answer = getUserInput();

if (answer.toLowerCase().startsWith("y")) {
return true;
} else {
return false;
}
}

private String getUserInput() {


// getting user input code here...
}
}

FEUP ● Nuno Flores ●


138

69
9/22/11

The  Hollywood  Principle  


wood
Holly iple -
 “Don’t  call  us,  we’ll  call  you”   c
Prin t call us,
“Don’ all you”.!
 Eliminates  high-­‐level  to  low-­‐level  dependency  of   we’ll c
components,  and  vice-­‐versa  
 Low-­‐level  components  “hook  up”  into  a  system,  but  only  
high-­‐level  components  decide  when  they  need  them  
• The  “don’t  call  us,  we’ll  call  you”  treatment  
• Ironically,  they  don’t  even  know  how  they  are  actually.  

High-Level
Component
The high-level components
control the when and how

Low-Level Low-Level
Component Component

A low-level component
Low-level components can Low-Level never calls a high-level
participate in the Component component directly
computation

FEUP ● Nuno Flores ●


139

Sorting  with  TEMPLATE  METHOD  


 Where  are  the  template  method  and  hook(s)  here?  
public static void sort(Object[] a) {
Object aux[] = (Object[])a.clone();
mergeSort(aux, a, 0, a.length, 0);
}

public static void mergeSort(Object src[], Object dest[],


int low, int high, int off)
{
for (int i = low; i < high ; i++) {
for (int j = i ; j > low &&
((Comparable) dest[j-1].compareTo((Comparable)dest[j])>0; j--)
{
swap(dest, j, j-1);
}
}

 What  if  I  wanted  to  sort  Ducks?  


FEUP ● Nuno Flores ●
140

70
9/22/11

Comparing  Ducks  and  Ducks  


We need to implement the
public class Duck implements Comparable { Comparable interface
String name; Our Ducks have a name
int weight; and a weight

public Duck(String name, int weight) {


this.name = name;
this.weight = weight;
}

public String toString() {


return name + " weighs " + weight;
}
hook method that
mergeSort() needs to
compare objects, in this
public int compareTo(Object object) { case, Ducks

Duck otherDuck = (Duck)object;

if (this.weight < otherDuck.weight) {


return -1;
} else if (this.weight == otherDuck.weight) {
return 0;
} else { // this.weight > otherDuck.weight
return 1;
}
} Ducks are compared
according to their weight
}
FEUP ● Nuno Flores ●
141

TEMPLATE  METHOD  sightings…  


 Sheeshhh…almost  everywhere!!  
 One  example:  Swingin’  with  Frames  
We’ve extend Jframe, that has the
template method update() that
controls updating the screen. We
public class MyFrame extends JFrame { hook in overriding the paint()
hook method
public MyFrame(String title) {
super(title);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

this.setSize(300,300);
this.setVisible(true);
JFrame’s update algorithm calls
} paint(). By default paint() does
nothing...it’s a hook.
public void paint(Graphics graphics) {
super.paint(graphics);
String msg = "I rule!!";
graphics.drawString(msg, 100, 100);
} We’re overriding paint() and telling
the JFrame to draw a message in
the window
public static void main(String[] args) {
MyFrame myFrame = new MyFrame("Head First Design
Patterns");
}
}
FEUP ● Nuno Flores ●
142

71
9/22/11

Design  Billboard   ily bstrac


ory -
t Fact for
ace
OO Ba
sics!
a fam teA interf Abstr
efines
gy - d s, encapsu emProv
la s ide na milies of action
S tr a te
orithm kes th gycreatin
g fa dent !
OO Principles! of alg e, and ma Stttraach depen Encap
te
earbl-e.A vary rela
ted or hout - crete sulatio
each onon a
e-gto w it th o d onr
ec
tea
rc hoarn
l hm clnieants
ts
objec ry Mg theiarcecfo
e n!
efininesD thdeitaiolgnorait s to Fascpto Polym
ver - d letsacy d denibtlilyitfrieom ecifyaininterf ct but let orphis
Obsearny dependsen thd ep
asten
p on s ic a ll y.Definleesn
ib s es.!
n a ob je ich m!
o ret use itdynam ide wh
in .!
to-m n objects thaaob e flexclatigng Inherit
Encapsulate what varies.! ch nje
es
gct provid crsea sin sses dec ate. ance!
betwee e object epen dor
Dec
tors
enats
e to su
bclasubcla instanti
ts a
on to
when all of its d upadltaaer tendativ g class y Metth hod le tion
Favor composition over inheritance.! state, ified- aEnndsurefor extendin ctor verer ts inestantia
e t
ot o n a lity terF-aCson
.!
d ef in toses.!
l
n .! n s s
Sinasaguon
re ca one
ll y io
nct psulaA s ap cla a claubcla ts
ted s s
m ahti
a s fu
a of e s ie n id a
es
toly e - Enca ace to th ace cl -orPkrovace to a set
Program to interfaces, not clas ce andom provaid nd to object
, interf in terfa csaesdewin
n
insta l poinat re
C of um accesass na nother F
clasif rf
dn’t te in a
implementations.! q est ing you witha ect. Lets uco n uie
ld s
globa y lett nts exorp that seteof rface acade
thereb eterize clie , queueto gether ecofauin ms. .!F er-level
it.! param nt requests support herwise b suin yrf
bste steace
Strive for loosely coupled high the
differe uests, andons.! ot
m p a tibledefines a at makes se.!
designs between object that q
log re ble operati inco te rf ace th sier to u
d oa in te m ea
interact.! n s
u
subsy

Classes should be open for


extension but closed for
modification.!
- De m fine
Depend on abstractions. Do not ethod ith
late M n algor
depend on concrete classes.! Temp eleton of a deferring
Only talk to your friends.! the sk tion,
opera es. class s
in an steps to sub subclasse
Don’t call us, we’ll call you.! s o m e e t h o d o f a n
late M steps
Temp ne certain t
d e f i i t h o u m’s
re w
ithm gorith
algor ing the al
chang ure.!
struct
FEUP ● Nuno Flores ●
143

Challenge  
 Create  a  class  called  MakeEggs  that  allows  sub-­‐classes  to  
customize  the  way  they  bake  eggs.  
• Of  course,  there  is  always  a  ordered  procedure  to  make  eggs…  
• And  some  things  can’t  change…  
 

FEUP ● Nuno Flores ●


144

72
9/22/11

Diner  and  Pancake  House  Merge  


 Agree  on  MenuItem  definition  
public class MenuItem {
String name;
String description;
boolean vegetarian;
double price;

public MenuItem(String name,


String description,
boolean vegetarian,
double price)
{
// constructor code here...
}

public String getName() {


return name;
}

public String getDescription() {


return description;
}

public double getPrice() {


return price;
}

public boolean isVegetarian() {


return vegetarian;
}
}
FEUP ● Nuno Flores ●
145

Diner  and  Pancake  House  Merge  


 Disagree  on  Menu  implementation  
• Pancake  House  menu  
public class PancakeHouseMenu implements Menu {
ArrayList menuItems;

public PancakeHouseMenu() {
menuItems = new ArrayList();

addItem("K&B's Pancake Breakfast",


"Pancakes with scrambled eggs, and toast",
true,
2.99);

// adding other items here...

public void addItem(String name, String description,


boolean vegetarian, double price)
{
MenuItem menuItem =
new MenuItem(name, description, vegetarian, price);
menuItems.add(menuItem);
}

public ArrayList getMenuItems() {


return menuItems;
}

// other menu methods here


FEUP ● Nuno Flores ●
} 146

73
9/22/11

Diner  and  Pancake  House  Merge  


 Disagree  on  Menu  implementation  
• Diner  menu  
public class DinerMenu implements Menu {
static final int MAX_ITEMS = 6;
int numberOfItems = 0;
MenuItem[] menuItems;

public DinerMenu() {
menuItems = new MenuItem[MAX_ITEMS];

addItem("Vegetarian BLT",
"(Fakin') Bacon with lettuce & tomato on whole wheat", true, 2.99);
// add other items here...
}

public void addItem(String name, String description,


boolean vegetarian, double price)
{
MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
if (numberOfItems >= MAX_ITEMS) {
System.err.println("Sorry, menu is full! Can't add item to menu");
} else {
menuItems[numberOfItems] = menuItem;
numberOfItems = numberOfItems + 1;
}
}

public MenuItem[] getMenuItems() {


return menuItems;
}

// other menu methods here


} FEUP ● Nuno Flores ●
147

The  problem?  
 Java-­‐Enabled  “Waitress”  specification  
• printMenu()  
-­‐ prints  every  item  on  the  menu  
• printBreakfastMenu()  
...
-­‐ prints  just  breakfast  items   PancakeHouseMenu pancakeHouseMenu = new PancakeHouseMenu();
ArrayList breakfastItems = pancakeHouseMenu.getMenuItems();
• printLunchMenu()  
-­‐ prints  just  lunch  items   DinerMenu dinerMenu = new DinerMenu();
MenuItems[] lunchItems = dinerMenu.getMenuItems();
• printVegetarianMenu()   ...
-­‐ prints  all  vegetarian  menu  items  
• isItemVegetarian(name)  
-­‐ given  the  name  of  an  item,  returns  true  it  the  
item  is  vegetarian,  otherwise  returns  false.  
Now, we have to implement two
different loops to step through the
two implementations of the menu
for (int i = 0 ; i < breakfastItems.size(); i++) { items...
MenuItem menuItem = (MenuItem) breakfastItems.get(i);
System.out.print(menuItem.getName() + “ “);
System.out.print(menuItem.getPrice() + “ “);
System.out.print(menuItem.getDescription()); ...one loop the the ArrayList...
}

for (int i = 0 ; i < lunchItems.length(); i++) {


MenuItem menuItem = lunchItems[i]; ...and another for the Array.
System.out.print(menuItem.getName() + “ “);
System.out.print(menuItem.getPrice() + “ “);
System.out.print(menuItem.getDescription());
}
FEUP ● Nuno Flores ●
148

74
9/22/11

Array

Can  we  encapsulate  the  iteration?   0


for (int i = 0 ; i < lunchItems.length; i++) {
MenuItem menuItem = lunchItems[i]; lunchItems[0] MenuItem
}
lunchItems[1]
for (int i = 0 ; i < breakfastItems.size(); i++) { 1
MenuItem menuItem = (MenuItem)breakfastItems.get(i); MenuItem
} lunchItems[2]
get(3)
get(2)
get(1) 2
get(0)
MenuItem
lunchItems[3]

3
MenuItem MenuItem MenuItem MenuItem
MenuItem
0 1 2 3
ArrayList Iterator iterator = lunchMenu.createIterator();

while (iterator.hasNext()) {
MenuItem menuItem = (MenuItem)iterator.next();
} Array
Iterator iterator = breakfastMenu.createIterator();
next()
while (iterator.hasNext()) { 0
MenuItem menuItem = (MenuItem)iterator.next(); lunchItems[0] MenuItem
} Iterator

next() lunchItems[1]
1

MenuItem
Iterator lunchItems[2]

get(3)
get(2) 2
get(1)
get(0)
MenuItem
lunchItems[3]

3
MenuItem MenuItem MenuItem MenuItem MenuItem
0 1 2 3 FEUP ● Nuno Flores ●
ArrayList 149

Meet  the  ITERATOR  pattern  


 Enables  to  iterate  across  any  kind  of  collection  (or  
aggregate)  of  objects:  arrays,  lists,  hashtables,  sets,  …  
 Relies  on  an  interface:  
The hasNext() method tells us if
<<interface>>
Iterator
there are more elements in the
aggregate to iterate through.
hasNext()
next() The next() method returns the
next object in the aggregate.

 Concrete  iterators  implement  this  interface,  that  is…  


<<interface>>
Iterator
hasNext()
next()

DinerMenuIterator DinerMenuIterator is an
implementation of Iterator
hasNext() that knows how to iterate
next()
over an array of MenuItems.
FEUP ● Nuno Flores ●
150

75
9/22/11

Adding  an  Iterator  to  DinerMenu  


 Interface…  
public interface Iterator {
boolean hasNext();
Object next();
}
 …and  the  concrete  iterator.  
We implement the Iterator
interface
public class DinerMenuIterator implements Iterator {
MenuItem[] items;
position maintains the
int position = 0;
current position of the
iteration over the array
public DinerMenuIterator(MenuItem[] items) {
this.items = items; The constructor takes the
} array of menu items we are
going to iterate over.
public Object next() {
MenuItem menuItem = items[position]; The next() method returns
position = position + 1; the next item in the array and
return menuItem; increments the position
}

public boolean hasNext() {


if (position >= items.length || items[position] == null) {
return false;
} else { We also need to check if the
return true; item is null, because in the
} The hasNext() method checks to
array we have a max size
} allocated.
see if we’ve seen all the elements
} of the array and returns true if
there are more to iterate through.

FEUP ● Nuno Flores ●


151

Reworking  the  DinerMenu  with  Iterator  


 Inserting  createIterator()  method  
public class DinerMenu implements Menu {
static final int MAX_ITEMS = 6;
int numberOfItems = 0; We’re not going to need the getMenuItems()
MenuItem[] menuItems; method anymore and in fact we don’t want it
because it exposes our internal internal
// constructor here... implementation!

// addItem here...

public MenuItem[] getMenuItems() {


return menuItems; Here’s the createIterator() method. It
} creates a DinerMenuIterator from the
menuItems array and returns it to the
client.
public Iterator createIterator() {
return new DinerMenuIterator(menuItems);
}

// other menu methods here


} We’re returning the Iterator interface. The client doesn’t need
to know how the menuItems are maintained in the DinerMenu,
nor does it need to know how the DinerMenuIterator is
implemented. It just needs to use the iterators to step through
the items in the menu.

FEUP ● Nuno Flores ●


152

76
9/22/11

Fixing  up  the  Waitress  code…  


public class Waitress {
In the constructor, the Waitress
PancakeHouseMenu pancakeHouseMenu; takes the two menus
DinerMenu dinerMenu;

public Waitress(PancakeHouseMenu pancakeHouseMenu, DinerMenu dinerMenu) {


this.pancakeHouseMenu = pancakeHouseMenu;
this.dinerMenu = dinerMenu; The printMenu() method now
} creates two iterators, one for
each menu
public void printMenu() {
Iterator pancakeIterator = pancakeHouseMenu.createIterator();
Iterator dinerIterator = dinerMenu.createIterator();

System.out.println("MENU\n----\nBREAKFAST");
printMenu(pancakeIterator);
System.out.println("\nLUNCH"); And then calls the overloaded
printMenu(dinerIterator); printMenu() with each iterator
}
test if there are any
private void printMenu(Iterator iterator) { more items
while (iterator.hasNext()) {
MenuItem menuItem = (MenuItem)iterator.next(); get the next item
System.out.print(menuItem.getName() + ", ");
System.out.print(menuItem.getPrice() + " -- ");
System.out.println(menuItem.getDescription());
}
The overloaded printMenu()
} method uses the Iterator to
step through the menu items
// other methods here... Note: we’re down and print them.
} to one loop.

FEUP ● Nuno Flores ●


153

What  we  have  so  far…  


Decoupling: Waitress is
tightly-coupled: Waitress is decoupled from the actual
still dependent of the concrete implementation of the
menus. We’ll fix this next! concrete iterator classes

PancakeHouseMenu <<interface>>
Waitress Iterator
menuItems
printMenu() hasNext()
next()
createIterator()

DinerMenu

menuItems PancakeHouseMenuIterator DinerMenuIterator

createIterator() hasNext() hasNext()


next() next()

Encapsulated iteration:
implementation lives outside
the aggregate with only a few
methods to allow traversal.

FEUP ● Nuno Flores ●


154

77
9/22/11

Decoupling  Waitress  from  concrete  menu  classes.  

 Create  common  interface  for  menus  


• “Program  to  an  interface,  not  an  implementation..”  
public interface Menu {
public Iterator createIterator();
}

 Rework  Waitress  a  little…  


public class Waitress {

Menu pancakeHouseMenu;
Menu dinerMenu;

public Waitress(Menu pancakeHouseMenu, Menu dinerMenu) {


this.pancakeHouseMenu = pancakeHouseMenu;
this.dinerMenu = dinerMenu;
}

// other methods stay the same ...


}

FEUP ● Nuno Flores ●


155

What  does  this  get  us?  

Our new Menu interface. It Now, Waitress only needs to


specifies the new method be concerned with Menus Full decoupling from
createIterator() and Iterators concrete classes!

<<interface>> <<interface>>
Waitress Iterator
Menu
Hum, this resembles the
createIterator() printMenu() hasNext()
FACTORY METHOD
next()
pattern...is it??

PancakeHouseMenu DinerMenu PancakeHouseMenuIterator DinerMenuIterator


menuItems menuItems
hasNext() hasNext()
next() next()
createIterator() createIterator()

FEUP ● Nuno Flores ●


156

78
9/22/11

ITERATOR  pattern  defined   ovide


a way
f
r - Pr elements o
 Allows  traversal  of  the  elements  of  an   terato
I set h t
es jec
aggregate  without  exposing  the  underlying   to acc gregate ob hout
an ag ntially wit erlying
implementation.   seque g its und
n
exposi entation.!
 Places  the  task  of  traversal  on  the  iterator   repres
object,  not  on  the  aggregate.  
 Places  the  responsibility  where  it  should  be  
• Simplifying  the  aggregate  interface  

FEUP ● Nuno Flores ●


157

Single  Responsability   uld


ss sho
A cla nly one
 Every  responsability  of  a  class  is  an  area  of  potential   have o to
change.   reason e.!
chang
• Handling  aggregate  +  handling  iteration  
• Both  collection  and  iteration  can  change  
-­‐ Collection  may  change.  
-­‐ Way  to  iterate  may  change.  

 More  than  on  responsibility  means  more  than  one  


area  of  change  
 Principle:  Keep  each  class  to  a  single  responsibility  
• Keep  the  cohesion  of  a  class  
-­‐ Has  only  methods  that  are  closely  related.  

 Remember:  Whenever  CHANGE  finds  an  


opportunity,  it  crepts  in…  

FEUP ● Nuno Flores ●


158

79
9/22/11

Now  there’s  a  Café  Menu  


 Integrate  this  class  into  our  framework…  
public class CafeMenu {
Hashtable menuItems = new Hashtable();

public CafeMenu() {
addItem("Veggie Burger and Air Fries",
"Veggie burger on a whole wheat bun, lettuce, tomato, and fries",
true, 3.99);
addItem("Soup of the day",
"A cup of the soup of the day, with a side salad",
false, 3.69);
addItem("Burrito",
"A large burrito, with whole pinto beans, salsa, guacamole",
true, 4.29);
}

public void addItem(String name, String description,


boolean vegetarian, double price)
{
MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
menuItems.put(menuItem.getName(), menuItem);
}
}

 Take  a  look  at  MenuTestDrive…  


FEUP ● Nuno Flores ●
159

Just  when  we  thought  it  was  safe…  


 Now  they  want  to   All Menus
add  a  dessert   ArrayList with all the menus

submenu.   PancakeHouse DinerMenu CafeMenu


Menu
0 1 2

Pancake Menu Café Menu


Diner Menu
MenuItem MenuItem MenuItem MenuItem
Key MenuItem
0 1 2 3 0
MenuItem

Key MenuItem
1
MenuItem

Key MenuItem
Dessert Menu
2
MenuItem
0 Key MenuItem

MenuItem 3
MenuItem

1
Hashtable
MenuItem

We can’t assign a dessert


2 menu to a MenuItem array!!
MenuItem

3
MenuItem

FEUP ● Nuno Flores ●


160

80
9/22/11

What  do  we  need?  


 Some  kind  of  tree  shaped  structure  
• It  will  accommodate  menus,  submenus  and  menu  items.  

 A  way  to  traverse  the  items  in  each  menu.  


• As  convenient  as  what  we  are  doing  now  with  iterators.  

 Traverse  the  items  in  a  more  flexible  manner  


• Over  only  the  Diner’s  dessert  menu  
• Over  the  Diner  ‘s  entire  menu,  including  the  dessert  submenu.  

 We  must  refactor  our  code  in  order  for  it  to  grow  
• Otherwise,  would  leave  us  a  rigid,  inflexible  code,  unprone  to  change.  

FEUP ● Nuno Flores ●


161

That  is…  
We need to accommodate
Menus... All Menus

… and sub menus...


PancakeHouse PancakeHouse
Diner Menu
Menu Menu

MenuItem MenuItem MenuItem MenuItem MenuItem MenuItem MenuItem MenuItem MenuItem


Dessert Menu

We need to be able
to traverse all items … and menu items.
in the tree.
MenuItem MenuItem MenuItem MenuItem

We also need to be able to


traverse more flexibly, for
instance over one menu.

FEUP ● Nuno Flores ●


162

81
9/22/11

The  COMPOSITE  pattern   - Com res


pose
 Allows  us  to  build  structures  of  objects  in  the  form  of  trees   Composite tree structu e
s in t o -who l
• Contain  both  compositions  of  objects  and  individual  objects  as  nodes   object esent part posite lets
r
• We  can  apply  the  same  operations  over  both  composites  and   to rep chies. Com vidual
i
individual  objects.  
hierar s treat ind ositions of
• We  can  ignore  their  differences.   c l i e n t c o m p
s and y.!
 Creates  part-­‐whole  hierarchies   object uniforml
b je c t s
o

The Component defines an interface


The Client uses the Component for all objects in the compostion: both The Component may implement a
interface to manipulate the the composite and the leaf nodes. default behaviour for add(), remove(),
objects in the composition. getChild() and its operations.

A Leaf has no
children.

A Leaf defines the behaviour for the


elements in the composition. It does
this by implementing the operations The Composite’s role is to define
the Composite supports. The Composite also implements the Leaf- behaviour of the components having
related operations. Note that some of these children and to store child components
may not make sense on a Composite, so in
FEUP ● Nuno Flores ●
that case an exception might be generated. 163

Designing  Menus  with  COMPOSITE  


Component

Client
MenuComponent

Waitress getName()
getDescription()
getPrice()
isVegetarian()
print()
Methods for manipulating add(MenuComponent)
the components remove(MenuComponent)
getChild(int)

Leaf

Composite
MenuItem Menu

getName() menuComponents
getDescription()
getPrice() getName()
isVegetarian() getDescription()
print() print()
add(MenuComponent)
remove(MenuComponent)
getChild(int)

FEUP ● Nuno Flores ●


164

82
9/22/11

Implementing  the  Menu  Component  


public abstract class MenuComponent {

public void add(MenuComponent menuComponent) { The “composite”


throw new UnsupportedOperationException(); methods
}
public void remove(MenuComponent menuComponent) {
throw new UnsupportedOperationException();
}
public MenuComponent getChild(int i) {
throw new UnsupportedOperationException();
}

public String getName() {


throw new UnsupportedOperationException();
}
public String getDescription() {
throw new UnsupportedOperationException(); The “operation”
} methods
public double getPrice() {
throw new UnsupportedOperationException();
}
public boolean isVegetarian() {
throw new UnsupportedOperationException();
}

public void print() {


throw new UnsupportedOperationException();
}
}
FEUP ● Nuno Flores ●
165

Implementing  the  Menu  Item  


public class MenuItem extends MenuComponent {
String name;
String description;
boolean vegetarian;
double price;

public MenuItem(String name,


String description,
boolean vegetarian,
double price)
All methods
{
remain the same
// constructor code here... as previous
} implementation...

// getter methods here...


...except for print().
public void print() { Overriding this method to
System.out.print(" " + getName()); print the complete menu
if (isVegetarian()) { entry.
System.out.print("(v)");
}
System.out.println(", " + getPrice());
System.out.println(" -- " + getDescription());
}
}

FEUP ● Nuno Flores ●


166

83
9/22/11

Implementing  the  Composite  Menu  …  


Menu is also a
public class Menu extends MenuComponent { MenuComponent like
ArrayList menuComponents = new ArrayList(); MenuItem
String name;
String description;

public Menu(String name, String description) { Now Menu has a name and a
this.name = name; description. Earlier we had a
this.description = description; different class for each menu.
}

public void add(MenuComponent menuComponent) {


menuComponents.add(menuComponent); To add a Menu or MenuItem we
} just need one method to do both.

public void remove(MenuComponent menuComponent) {


menuComponents.remove(menuComponent);
}

public MenuComponent getChild(int i) {


return (MenuComponent)menuComponents.get(i);
}
Here are the getter methods for
name and description.
public String getName() {
return name;
} We aren’t overriding getPrice() or
isVegetarian() because those methods
don’t make sense for a Menu. Any call will
public String getDescription() { throw an exception.
return description;
}
...
FEUP ● Nuno Flores ●
167

…and  its  print()  method.  

...

public void print() {


System.out.print("\n" + getName());
System.out.println(", " + getDescription());
System.out.println("---------------------");

Iterator iterator = menuComponents.iterator();


while (iterator.hasNext()) {
We use an ITERATOR!! We iterate through MenuComponent menuComponent =
all of the Menu’s components (items or
menus alike). As both have print(), we just (MenuComponent)iterator.next();
need to call it and the rest is up to them. menuComponent.print();
}
}
}
if during this iterator, we encounter another
Menu object, its print() method will start
another iteration, and so on.
 test  drive  it…  
 Can  we  replace  “recursion”  
by  “iteration”?  
FEUP ● Nuno Flores ●
168

84
9/22/11

Flashback  to  Iterator  


 How  to  use  Iterator  with  a  Composite  
MenuComponent • Lets  add  createIterator()    to  MenuComponent  
getName() -­‐ So  Menu  and  MenuItem  have  to  implement  it…  
getDescription()
getPrice()
isVegetarian()
public class Menu extends MenuComponent { ArrayList
print() public Iterator createIterator() {
add(MenuComponent) return new CompositeIterator(menuComponents.iterator());
remove(MenuComponent)
getChild(int)
}
createIterator() }
}
public class MenuItem extends MenuComponent {
public Iterator createIterator() {
return new NullIterator();
}
}
}
import java.util.Iterator;

public class NullIterator implements Iterator {

public Object next() {


return null;
}

public boolean hasNext() {


return false;
}

public void remove() {


throw new UnsupportedOperationException();
}
}
FEUP ● Nuno Flores ●
169

Iterator  &  Composite  together…  


 The  CompositeIterator  
import java.util.*;

public class CompositeIterator implements Iterator {


Stack stack = new Stack();

public CompositeIterator(Iterator iterator) { The iterator of the top level composite


stack.push(iterator); we’re going to iterate over is passed in.
} We throw that in a stack data structure.

public Object next() { Okay, when the client wants to get


if (hasNext()) { the next element we first make sure
Iterator iterator = (Iterator) stack.peek(); there is one by calling hasNext()...
MenuComponent component = (MenuComponent) iterator.next();
if (component instanceof Menu) {
stack.push(component.createIterator());
} if there is a next element, we get
return component; the current iterator off the stack and
} else { get its next element.
If that element is a menu, we have
return null;
another composite that needs to
}
be included in the iteration, so we
}
throw it in the stack. In either
public boolean hasNext() { case, we return the component.
if (stack.empty()) {
return false;
To see if there is a next element,
} else {
we check to see if the stack is
Iterator iterator = (Iterator) stack.peek();
if (!iterator.hasNext()) { empty, if so, there isn’t.
stack.pop();
return hasNext(); Otherwise, we get the iterator off the
} else { top of the stack and see if it has a next
return true; element. If it doesn’t we pop it off the
} stack and call hasNext() recursively.
} Otherwise, there is a next
} element and we return true.
public void remove() {
throw new UnsupportedOperationException();
}
} We are not suporting
remove, just traversal. FEUP ● Nuno Flores ●
170

85
9/22/11

Design  Billboard   ily bstrac


ory -
t Fact for
ace
OO Ba
sics!
a fam teA interf Abstr
efines
gy - d s, encapsu emProv
la s ide na milies of action
S tr a te
orithm kes th gycreatin
g fa dent !
OO Principles! of alg e, and ma Stttraach depen Encap
te
earbl-e.A vary rela
ted or hout - crete sulatio
each onon a
e-gto w it th o d onr
ec
tea
rc hoarn
l hm clnieants
ts
objec ry Mg theiarcecfo
e n!
efininesD thdeitaiolgnorait s to Fascpto Polym
ver - d letsacy d denibtlilyitfrieom ecifyaininterf ct but let orphis
Obsearny dependsen thd ep
asten
p on s ic a ll y.Definleesn
ib s es.!
n a ob je ich m!
o ret use itdynam ide wh
in .!
to-m n objects thaaob e flexclatigng Inherit
Encapsulate what varies.! ch nje
es
gct provid crsea sin sses dec ate. ance!
betwee e object epen Dec enats
dor tors
e to su
bclasubcla instanti
ts a
on to
when all of its d upadltaaer tendativ g class y Metth hod le tion
Favor composition over inheritance.! state, ified- aEnndsurefor extendin ctor verer ts inestantia
e t
ot o n a lity terF-aCson
.!
d ef in toses.!
l
n .! n s s
Sinasaguon
re ca one
ll y io
nct psulaA s ap cla a claubcla ts
ted s s
m ahti
a s fu
a of e s ie n id a
es
toly e - Enca ace to th ace cl -orPkrovace to a set
Program to interfaces, not clas ce andom provaid nd to object
, interf in terfa csaesdewin
n
insta l poinat re
C of um accesass na nother F
clasif rf
dn’t te in a
implementations.! q est ing you witha ect. Lets uco n uie
ld s
globa y lett nts exorp that seteof rface acade
thereb eterize clie , queueto gether ecofauin ms. .!F er-level
it.! param nt rein quests ort herwise b suin yrf
bste steace
Strive for loosely coupled igh e
dhifofedre- D ef ,e and supp ot p a tible efines a h t makes the.!
ce tha sier to us
ts
eshm ation s. ! m d
designs between object that la te M etlog re
a lg qoruit
op er inco te rf a
interact.! Tempeleton of n,uadnefdoa blne g
ri
in s te m ea
the sk on lasses.
er subsy
operati bc
in na steps to su subclasses
Classes should be open for some ate Method eps of an g
extension but closed for Templ e certain stt changin
pose
redefin withou ructure.!
res - Com
osite tree structu
ithm
modification.! algor orithm’s st
the alg
s in t who l Comp o e
Depend on abstractions. Do not object esent part- posite lets
depend on concrete classes.! w a y t o r e pr . C o m al
ea chie s ividu
Only talk to your friends.! t o r - Provid ents of hierar s treat ind ositions of
Itera ess the ele ject
m t
clien and com y.!
s
p
Don’t call us, we’ll call you.! to acc gregate ob hout object uniforml
t s
a g w i t b je c
lying
an o
A class should have only one ially
nt er
reason to change.! seque g its und
p o s i n n . !
ex io
entat
repres
FEUP ● Nuno Flores ●
171

Challenge    
 A  company  wants  to  build  a  tree-­‐like  system  for  storing  data  
about  its  departments  and  employees.  There  are  Tecnicians,  
Laborers  and  Supervisors.  The  supervisors  may  supervise  
other  Employees  including  other  supervisores.    
 One  functionality  includes  printing  the  names  of  the  
employees  supervised  by  a  certain  supervisor.  
 Solve  their  problem…  

FEUP ● Nuno Flores ●


172

86
9/22/11

Gumball  Machine  
 State  machine  
turns crank

Has Quarter

inserts quarter
Gumball Sold

No Quarter

dispense gumball [ gumballs > 0 ]

dispense gumball [ gumballs == 0 ]


Out of
Gumballs

FEUP ● Nuno Flores ●


173

A  straightforward  implementation…  
public class GumballMachine {

final static int SOLD_OUT = 0;


final static int NO_QUARTER = 1;
final static int HAS_QUARTER = 2;
final static int SOLD = 3;

int state = SOLD_OUT;


int count = 0;

public GumballMachine(int count) {


this.count = count;
if (count > 0) {
state = NO_QUARTER;
}
}

public void insertQuarter() {


if (state == HAS_QUARTER) {
System.out.println("You can't insert another quarter");
} else if (state == NO_QUARTER) {
state = HAS_QUARTER;
System.out.println("You inserted a quarter");
} else if (state == SOLD_OUT) {
System.out.println("You can't insert a quarter, the machine is sold out");
} else if (state == SOLD) {
System.out.println("Please wait, we're already giving you a gumball");
}
}
...

 Take  a  look  at  the  rest  of    the  code…  (/state/gumball)  

FEUP ● Nuno Flores ●


174

87
9/22/11

Here  comes  our  friend…CHANGE!!!!  


 New  State:  “Winner”  
• Everytime  the  crak  is  turned,  the  customer  gets  2  gumballs  instead  of  
one.  

 Repercussions??  
final static int SOLD_OUT = 0;
final static int NO_QUARTER = 1; First, you’d have to add a new WINNER
final static int HAS_QUARTER = 2; state here. That isn’t too bad...
final static int SOLD = 3;

public void insertQuarter() {


// insert quarter code here...
}

public void ejectQuarter() { ...but then, you’d have to add a new


// eject quarter code here... conditional in every single method
} to handle the WINNER state; that’s a
lot of code to modify.
public void turnCrank() {
// turn crank here...
}
turnCrank() will get specially messy,
because you’d have to add code to
public void dispense() { check to see whether you’ve got a
// dispense code here... WINNER and then switch to either the
} WINNER state or the SOLD state

...
FEUP ● Nuno Flores ●
175

The  new  design…  


1. Create  an  interface  for  State,  which  all  states  implement.  
2. Implement  a  State  class  for  all  our  states  
 Responsible  for  the  behaviour  of  that  state.  

3. Dump  all  conditional  code  and  delegate  the  work  to  the  state  class  

<<interface>> Here’s the interface for all states. The


State methods map directly to actions that
could happen to the Gumball Machine.
insertQuarter()
ejectQuarter()
turnCrank()
dispense()

...and later on, we’ll need this one


SoldState SoldOutState NoQuarterState HasQuarterState

insertQuarter() insertQuarter() insertQuarter() insertQuarter()


ejectQuarter() ejectQuarter() ejectQuarter() ejectQuarter()
turnCrank() turnCrank() turnCrank() turnCrank() WinnerState
dispense() dispense() dispense() dispense()
insertQuarter()
ejectQuarter()
turnCrank()
...and we map each state dispense()
directly to a class.
FEUP ● Nuno Flores ●
176

88
9/22/11

Implementing  our  State  classes  


First, we need to implement the
State interface.

public class NoQuarterState implements State {


GumballMachine gumballMachine; We store the Gumball Machine in
an instance variable
public NoQuarterState(GumballMachine gumballMachine) {
this.gumballMachine = gumballMachine; If someone inserts a quarter, we print
a message saying the quarter was
} accepted and change the machine’s
state to HasQuarterState.
public void insertQuarter() {
System.out.println("You inserted a quarter");
gumballMachine.setState(gumballMachine.getHasQuarterState());
}

public void ejectQuarter() {


System.out.println("You haven't inserted a quarter");
}

public void turnCrank() {


System.out.println("You turned, but there's no quarter");
}

public void dispense() { The remaining actions don’t force any


System.out.println("You need to pay first"); state change or are inappropriate
}
}

FEUP ● Nuno Flores ●


177

Reworking  the  Gumball  Machine  


public class GumballMachine {

State soldOutState;
State noQuarterState;
State hasQuarterState; States are now classes,
State soldState; instead of integer constants.

State state = soldOutState;


int count = 0; State classes initialization

public GumballMachine(int numberGumballs) {


soldOutState = new SoldOutState(this);
noQuarterState = new NoQuarterState(this);
hasQuarterState = new HasQuarterState(this);
soldState = new SoldState(this);

this.count = numberGumballs; Initial state


if (numberGumballs > 0) {
state = noQuarterState;
}
}

public void insertQuarter() {


state.insertQuarter();
}

public void ejectQuarter() { The actions VERY EASY to


state.ejectQuarter(); implement: just delegate to the
} current state subclass.

public void turnCrank() {


state.turnCrank();
state.dispense();
}
The machine supports releaseBall()
void setState(State state) { helper method that releases the ball
this.state = state; and decrements the count instance
} variable

void releaseBall() {
System.out.println("A gumball comes rolling out the slot...");
if (count != 0) {
count = count - 1; There are still a few methods
} missing: getters for each State and
} getCount() FEUP ● Nuno Flores ●
178

89
9/22/11

Implementing  more  states  


public class SoldState implements State {

GumballMachine gumballMachine;

public SoldState(GumballMachine gumballMachine) {


this.gumballMachine = gumballMachine;
}

public void insertQuarter() {


System.out.println("Please wait, we're already giving you a gumball");
}

public void ejectQuarter() { All these methods are inappropriate


System.out.println("Sorry, you already turned the crank"); actions fot this state
}

public void turnCrank() {


System.out.println("Turning twice doesn't get you another gumball!");
}
Depending on the gumball count, it
If we are in this state, it means the either transits to tje NoQuarterState
public void dispense() { customer paid, so we release a gumball. or the SoldOutState
gumballMachine.releaseBall();
if (gumballMachine.getCount() > 0) {
gumballMachine.setState(gumballMachine.getNoQuarterState());
} else {
System.out.println("Oops, out of gumballs!");
gumballMachine.setState(gumballMachine.getSoldOutState());
}
}
}

FEUP ● Nuno Flores ●


179

What  have  we  done  so  far…  


 Re-­‐implemented  the  code…  
• Structurally  quite  different,  functionally  it  is  exactly  the  same…  
• In  a  pedagogical  way,  we  REFACTORED  TO  PATTERNS…  

 Improved  the  design  


• Localized  the  behaviour  of  each  state  into  its  own  class.  
• Removed  all  difficult  to  maintain  “if”  statements  
• Closed  each  state  for  modification,  opening  Gumball  Machine  open  
for  extension  (adding  new  states)  
• Created  a  code  base  and  class  strucutre  that  maps  more  closely  the  
Gumball  Machine  diagram  
-­‐ easier  to  read  and  understand…and  communicate.  

 And,  of  course,  used  the  STATE  pattern!  

FEUP ● Nuno Flores ●


180

90
9/22/11

STATE  pattern  defined…  


object
A l l o w an ur
- o
 Allows  encapsulating  state  change  behaviour.   Stateer its behavi l state
to alt its interna ect will
 Delegates  state  implementation  to  subclasses   when es. The obj its
chang to change
r
appea !
cl .
a s s
The State interface defines a common interface for
all concrete classes; the states all implement the
The Context is the class that can
same interface, so they are interchangeable.
have a number of internal states.

Whenever the request() is made


on the Context it is delegated ti
the state to handle
ConcreteStates handle requests from the
Context. They provide its own implementation
for a request. In this way, when the Context
changes state, its behaviour will change as
well. FEUP ● Nuno Flores ●
181

STATE  vs  STRATEGY  


 State  
• Alternative  to  putting  lots  of  
conditionals  in  your  context.  
• Encapsulating  behaviour  in  
context  state  objects.  

 Strategy  
• Flexible  alternative  to  subclassing.  
• Change  behaviour  by  composition  
instead  of  inheritance.  

FEUP ● Nuno Flores ●


182

91
9/22/11

Implementing  the  missing  states    


 WinnerState  
• 1  out  of  10  times    
• Changes  needed:  
-­‐ new  WinnerState  class  
-­‐ In  GumballMachine  
-­‐ In  HasQuarterState  

 If  there  was  a  refill()  action,  what  changes  would  there  be  


needed  to  implement  it?  
 
  turns crank
refill
Has Quarter

inserts quarter
Gumball Sold

No Quarter

dispense gumball [ gumballs > 0 ]

dispense gumball [ gumballs == 0 ]


Out of
Gumballs

FEUP ● Nuno Flores ●


183

Design  Billboard   tracat interface fo


Facto
ry -
r
OO Ba
sics!
a fam Abs
ily
efines psulatesrovide n s of Abstr
gy - d ca P milie action
OO Principles! Strate orithms, enakes them ating fa endent
Encap
!
of alg e, and m Stttraach tegycre ted or dep
ea ch on r
bl-e.A
agto hm vary nts jects wM
ea re la h ou t d - crete
it etho r conr sulatio
hoarne-
econ n!
tea
rc
efininesD thdeitaiolgnorait
l cliea ob ry g theiace fo Polym
ver - d letsacy d denibtlilyitfrieom s to n Fascpto ecifyaininterf ct but let orphis
Encapsulate what varies.! Obsearny dependsen astpen
dep onit s ic ally.Defibinleesn
es .!na obje h m !
ointh
re .! n a m ex
c la
vide flcreatig
s n g e whic Inherit
to-m jects that u
n ob gse
es dy
ct nje ts rs pro
aob decid
in es .
betwee e object ch enato bclassusbclassinstantiate a ance!
on epen Dec dor e to su to lets on
Favor composition over inheritance.! when all of its d upadltaaer tendativ g class y Metth hod ti
te , d re d in or erts insta a e n ti
sta ied- aEnnsu for extennality.! F-act
Convef
re lneottoifn ye.! s apter clasascldau
er
ss inatosses.!
Program to interfaces, not Sinasaguon tolymahtiacas ll
on
e fu
a
nctiopsulaA
ca
ted
a ce of the s bclclients vides a et
provaid
n
- E ct, interf to ace e -orPkro s
implementations.! clas ce andom nd to obje interf ad w terface to a
ascses
n
insta l poinat re
C of um accesass na nother cla
F in
q est ing you witha ect. Lets uco nif lddn’taces in a
uie
globa y lett e clients exorp th at in te rf ca de
Strive for loosely coupled th er eb
eteriz uests, qu ttoget eu e h er of s
ecaubsyos
e of
ste
F a
ms. .! er-level
designs between object that it.! param nt rein q ppor ot ay
a hwer wise b le inteprf
sCuom ae cehigs h akes the
ef ,e and su ros.v! ideenm
a re
dhifofedre- D ospitatie b- deftr
of inuesctu that m r to use.!
eshts
m ra-tiP
Cointscops into treeins-w
m
interact.! p la te Metnloagare lg
It
qorur
e
bl
it
eaoptoer on
g ess th e el em te rf
h ace
ol e
mtseas
ie
Tem eleton of ,udnefdoa erria ncc ject
obob ject ent part bsyitste le
the sk operation lato es. gregate itto rept resg s. Com
hou su pos e l
Classes should be open for bc ss alaassges y w erly hie individua s
in na steps to su sun bc ti a ll
ndhie ra in
rc
some ate Method epsseq uen
of aningg its u clients tr composit
eat ion
extension but closed for Templ e certain stt chexapnos gin tation.! s and ly.!
modification.! redefin withou ruct reuprere.!sen object cts uniform
it h m st of ob je
algor or ithm’s
the alg
Depend on abstractions. Do not
depend on concrete classes.!
ject
Only talk to your friends.!
l l o w an ob
-A our
Don’t call us, we’ll call you.! Stateer its behavi l state
to alt its interna ect will
when es. The obj its
A class should have only one
reason to change.!
chang to change
r
appea !
cla .
s s
FEUP ● Nuno Flores ●
184

92
9/22/11

Monitoring  the  Gumball  Machine  


public class GumballMachine {
// other instance variables here...
String location;

public GumballMachine(String location, int count) {


// other constructor code here...
this.location = location;
}

public String getLocation() {


return location();
}

// other methods here...


}

public class GumballMonitor {


GumballMachine machine;

public GumballMonitor(GumballMachine machine) {


this.machine = machine;
}

public void report() {


System.out.println("Gumball Machine: " + machine.getLocation());
System.out.println("Current inventory: " + machine.getCount() + " gumballs");
System.out.println("Current state: " + machine.getState());
}
}

 But  what  if  we  want  a  remote  monitoring?  Ideas?!?  


FEUP ● Nuno Flores ●
185

The  role  of  the  ‘remote  proxy’  


 A  remote  proxy  acts  as  a  local  representative  to  a  remote  
object.  
• “remote  object”  –  object  in  another  heap  (running).  
• Client  object  (Gumball  Monitor)  
-­‐ thinks  its  making  remote  method  calls…  
-­‐ …when  actually  is  calling  a  proxy,  that  handles  communication  details.  
The proxy pretends to be a
Remote Gumball
remote object but its just a
machine with a JVM.
Monitoring stand in for the Real Thing.
station desktop

Proxy
Gumball Gumball
Monitor Machine
Local Heap Remote Heap
Same as old code, only it The Remote object IS the
thinks its talking to the real Real Thing. It’s the object with
object, but actually its a proxy the method that actually does
the real work.l
FEUP ● Nuno Flores ●
186

93
9/22/11

The  PROXY  pattern  defined  


 Create  a  representative  object  that  controls   - Pro vide a
Proxy or
gate
access  to  another  object   surro older for
• Remote,  expensive,  need  of  securing…   placeh r object to it.!
e
anoth l access to
t r o
Both the Proxy and the RealSubject con
implement the Subject interface. This
allows any client to treat the proxy
just like the RealSubject.
Most commonly we use
realization instead of
generalization

The Proxy keeps a reference to the


This is where the real work is done. Subject, so it can forward requests
The Proxy only controls access to it. to the Subject when necessary.

FEUP ● Nuno Flores ●


187

Some  kinds  of  proxies  


Note: If you want, we can go into
Java RMI later, off the record...

Remote Proxy Virtual Proxy


The proxy creates the Real
request()
request() Subject when it’s needed.
request()

Proxy

Client Real Subject


Proxy

Client Real Subject


The proxy may handle the
request, or if the RealSubject has
been created, delegate the calls
Protection Proxy to the RealSubject Big “expensive to create” object

Submits request only if


Client has permission
request()  Firewall  proxy  
 Smart  Reference  Proxy  
Proxy
Real Subject
 Caching  Proxy  
Client

Proxy checks if client has


 Syncronization  Proxy  
permission make the request to
the Real Subject.
 Complexity  Proxy  (Facade  Proxy)  
 Copy-­‐On-­‐Write  Proxy  
 ...  
FEUP ● Nuno Flores ●
188

94
9/22/11

Displaying  CD  covers  


 Using  Virtual  proxy  as  a  surrogate  for  the  object  before  and  
while  its  being  created.  

FEUP ● Nuno Flores ●


189

Designing  the  CD  Cover  Virtual  Proxy  


<<interface>>
This is the Swing Icon interface Icon
used to display images in a
user interface. getIconWidth()
getIconHeight()
paintIcon()

ImageIcon ImageProxy
subject
getIconWidth() getIconWidth()
getIconHeight() getIconHeight()
paintIcon() paintIcon()

This is our proxy, which first displays


This is javax.swing.ImageIcon, a message and then when the image
a class that displays an Image. is loaded, delegates to ImageIcon to
display the image.

1. ImageProxy  first  creates  an  ImageIcon  and  starts  loading  if  from  a  
network  URL.  
2. While  the  bytes  of  the  image  are  being  retrieved,  ImageProxy  displays  a  
status  message  “loading”  
3. When  the  Image  is  fully  loaded  ImageProxy,  delegates  all  method  calls  
to  image  icon  (all  methods  seen  above)  
4. If  the  user  request  a  new  image,  we’ll  create  a  new  proxy  and  start  the  
process  again.  
FEUP ● Nuno Flores ●
190

95
9/22/11

Writing  the  Image  Proxy  (I)  


class ImageProxy implements Icon {

ImageIcon imageIcon; The imageicon is the REAL icn


that we eventually want to
URL imageURL; display when ti’s loaded.
Thread retrievalThread;
boolean retrieving = false; We pass the URL of the image
into the constructor. This is the
image we need to display once it’s
public ImageProxy(URL url) { imageURL = url; } loaded.

public int getIconWidth() {


if (imageIcon != null) {
return imageIcon.getIconWidth();
} else {
return 800;
} We return a default width and hieght
until the ImageIcon is loaded; then
} we turn it over to the imageIcon.

public int getIconHeight() {


if (imageIcon != null) {
return imageIcon.getIconHeight();
} else {
return 600;
}
}

...

FEUP ● Nuno Flores ●


191

Writing  the  Image  Proxy  (II)  


public void paintIcon(final Component c, Graphics g, int x, int y) {
if (imageIcon != null) { If we got an icon already, we go
ahead and tell it to paint itself...
imageIcon.paintIcon(c, g, x, y);
} else { ...if not, we display the “loading”
g.drawString("Loading CD cover, please wait...", x+300, y+190); message

if (!retrieving) {
retrieving = true;
retrievalThread = We don’t want to hang up the
If we aren’t already new Thread(new Runnable() { entire user interface so we use
another thread to retrieve the
trying to retrieve the public void run() { image.
image...
try {
...then start retrieving it. imageIcon = new ImageIcon(imageURL, "CD Cover");
Don’t worry, only one c.repaint();
thread calls paint. We instantiate the Icon object, but
} catch (Exception e) { the constructor won’t return until
the image is loaded.
e.printStackTrace(); When we have the image ,
} we tell Swing that we need
to be repainted.
}
});
retrievalThread.start();
}
}
}
}

FEUP ● Nuno Flores ●


192

96
9/22/11

Using  Java  API’s  Proxy  to  create  a  protection  proxy  

 Java  uses  what  is  called  a  dynamic  proxy  


• Because  it  is  created  in  runtime.  You  just  have  to  give  it  an  invocation  
handler.  

<<interface>> <<interface>>
Subject InvocationHandler
request() invoke()

The Proxy now consists of


two classes

Proxy
RealSubject
InvocationHandler
request()
request()
invoke()

The Proxy is generated by You supply the InvocationHandler, which


Java and implements the entire gets all method calls that are invoked on the
Subject interface. Proxy. It controls access to the methods of
the RealSubject

FEUP ● Nuno Flores ●


193

public interface PersonBean {

Matchmaking  Service   String getName();


String getGender();
String getInterests();
public class PersonBeanImpl implements PersonBean { int getHotOrNotRating();
String name;
String gender; void setName(String name);
String interests;
int rating; void setGender(String gender);
int ratingCount = 0; void setInterests(String interests);
void setHotOrNotRating(int rating);
public String getName() {
return name; }
}

 A  Person  
public String getGender() {
return gender;
}

public String getInterests() {


• Has  his/hers  own  attributes  
return interests;
} • Should  not  be  able  to  change  
public int getHotOrNotRating() { its  own  “Hot  or  Not”  rating  
if (ratingCount == 0) return 0;
return (rating/ratingCount); -­‐ Not  be  able  to  invoke  own  
} method  
-­‐ Only  others  should  do  it.  
public void setName(String name) {
this.name = name;
}

public void setGender(String gender) {


this.gender = gender;
}

public void setInterests(String interests) {


this.interests = interests;
}

public void setHotOrNotRating(int rating) {


this.rating += rating;
ratingCount++;
}
} FEUP ● Nuno Flores ●
194

97
9/22/11

Creating  a  Dynamic  Proxy  for  PersonBean  


<<interface>> <<interface>>
Subject

1. Create  two  InvocationHandlers  


InvocationHandler
request() invoke()

 One  for  owner  invocations  


Proxy

 Other  for  non-­‐owner  invocations  


RealSubject
InvocationHandler
request()
request()
invoke()

2. Write  the  code  that  creates  the  


We need two of these

dynamic  proxies  

Proxy OwnerInvocationHandler

3. Wrap  any  PersonBean  object  with  the   request() invoke()

appropriate  proxy  
Proxy NonOwnerInvocationHandler
request() invoke()

FEUP ● Nuno Flores ●


195

1.  Creating  the  Invocation  Handlers  (I)  


<<interface>>
InvocationHandler
1 invoke()
called on proxy

proxy.setHotOrNotRating(9); 2 Proxy calls invoke() on


the InvocationHAndler.

invoke(Object proxy, Method method, Object[] args)


The Method class, a part of
the reflection API, tells us all
about the method invoked.
The handler decides if it
3 forwards the request to the
RealSubject or not. If yes,
calls invoke() on the Method Only now we invoke it on the
RealSubject...

return method.invoke(person, args);


With the original arguments

FEUP ● Nuno Flores ●


196

98
9/22/11

1.  Creating  the  Invocation  Handlers  (II)  

public class OwnerInvocationHandler implements InvocationHandler {


PersonBean person;

public OwnerInvocationHandler(PersonBean person) {


this.person = person;
}

public Object invoke(Object proxy, Method method, Object[] args)


throws IllegalAccessException {
If the method is a getter, go
ahead and invoke it on the
try { real subject
if (method.getName().startsWith("get")) {
return method.invoke(person, args);
} else if (method.getName().equals("setHotOrNotRating")) {
throw new IllegalAccessException();
} else if (method.getName().startsWith("set")) { Otherwise, if it is the
setHotOrNoRating() method
return method.invoke(person, args); we disallow it by throwing an
} IllegalAccessException.
} catch (InvocationTargetException e) {
e.printStackTrace(); All setter methods are
} allowed...
return null;
} If the real subject throws an
} exception...
If any other method is called,
we don’t take a change and
deny it.

FEUP ● Nuno Flores ●


197

2.  Creating  and  instantiating  the  Proxy  object  

PersonBean getOwnerProxy(PersonBean person) {

return (PersonBean) Proxy.newProxyInstance(


person.getClass().getClassLoader(),
person.getClass().getInterfaces(),
new OwnerInvocationHandler(person));
}

 Check  the  MatchMakingTestDrive  class  to  see  it  in  action…  

FEUP ● Nuno Flores ●


198

99
9/22/11

Challenge  
 Add  a  container  to  PersonBean  where  you  can  add  
testemonials  by  friends.  
 Make  a  new  Proxy  for  friends  of  the  person,  that  only  allows  
adding  testemonials.  

FEUP ● Nuno Flores ●


199

Design  Billboard   tracat interface fo


Facto
ry -
r
OO Ba
sics!
a fam Abs
ily
efines psulatesrovide n s of Abstr
gy - d ca P milie action
Strate orithms, enakes them ating fa endent !
of alg e, and m Stttraach tegycre ted or dep Encap
on r
bl-e.A re la h ou t d - crete sulatio
OO Principles! ea ch
tea
rc agto hm vary nts jects wM
hoarne-
econ
ea it etho r conr
g theiace fo n!
efininesD thdeitaiolgnorait
l cliea ob ry
s to n Fascpto Polym
ver - d letsacy d denibtlilyitfrieom ecifyaininterf ct but let orphis
Obsearny dependsen astpen
dep onit s ic ally.Defibinleesn
es .!na obje h m !
ointh
re .! n a m ex
c la
vide flcreatig
s n g e whic Inherit
to-m jects that u
n ob gse
es dy
ct nje ts rs pro
aob decid
in es .
betwee e object ch enato bclassusbclassinstantiate a ance!
Encapsulate what varies.! on epen Dec dor e to su to lets on
when all of its d upadltaaer tendativ g class y Metth hod ti
te , d re d in or erts insta a e n ti
sta ied- aEnnsu for extennality.! F-act
Convef
Favor composition over inheritance.! re lneottoifn ye.! s apter clasascldau
er
ss inatosses.!
Sinasaguon tolymahtiacas ll
on
e fu
a
nctiopsulaA
ca
ted
a ce of the s bclclients vides a et
provaid
n
- E ct, interf to ace e -orPkro s
clas ce andom nd to obje interf ad w terface to a
ascses
Program to interfaces, not n
insta l poinat re
C of um accesass na nother cla
F in
q est ing you witha ect. Lets uco nif lddn’taces in a
uie
globa y lett e clients exorp at in rf de
implementations.! th er eb
eteriz uests, qu ttoget eu e h er th of s
ecaubsyos
te
e of
ste
F a ca
ms. .! er-level
it.! param nt rein q ppor ot ay
a hwer wise b le inteprf
sCuom ae ce
higs h akes the
ef ,e and su ros.v! ideenm
a re
Strive for loosely coupled dhifofedre- D ospitatie b- deftr
of inuesctu that m r to use.!
eshtsm ra-tiP
Cointscops into treeins-w
m
p la te Metnloagare lg
It
qorur
e
bl
it
eaopto
g ess
er on
th e el em te rf
h ace
ol e
mtseas
ie
designs between object that Tem eleton of ,udnefdoa erria ncc ject
obob ject ent part bsyitste le
the sk operation lato es. gregate itto rept resg s. Com
hou su pos e l
interact.! bc ss alaassges y w erly hie individua s
in na steps to su sun bc ti a ll ra in
rc
some ate Method epsseq uen
of aninggcit s undhie nts treat positio
n
Templ e certain sttow exanpnaos
gobin je t tion.! clie s and com mly.!
Classes should be open for ll chct reu.!sren
ta object cts unifor
redefin a te - hAou
wit revupiore
extension but closed for algS or itth m
ithm s beh
it’s
st ru a
state of ob je
lter
algaor terna
l
modification.! the to
its in object wil
l
when es. The its
changr to change
Depend on abstractions. Do not a
rovide
appea
depend on concrete classes.! s.!
-P
c las

Only talk to your friends.! Proxy e or


gat
surro older for
placeh r object to it.!
Don’t call us, we’ll call you.!
e
A class should have only one anoth l access to
reason to change.!
n t r o
co

FEUP ● Nuno Flores ●


200

100
9/22/11

Patterns  of  Patterns  


 Patterns  are  often  used  together  and  combined  within  the  
same  design  solution.  
 A  compound  pattern  combines  two  or  more  patterns  into  a  
solution  that  solves  a  recurring  or  general  problem.  
 Ever  heard  of  MVC  (Model-­‐View-­‐Controller)?  

FEUP ● Nuno Flores ●


201

Meet  the  Model-­‐View-­‐Controller  


 Imagine  your  MP3  player…  
The display view is
updated for you
You use the interface and
your actions to go to the
you see the song on display controller
and hear it playing “play new song”

View Controller
The model notifies the
view of a change in
state
my state has changed!
update yourself! “player.play()

controller manipulates
The model contains all the state, data, the model
and application logic needed to Model
amaintain and play mp3s.

FEUP ● Nuno Flores ●


202

101
9/22/11

A  closer-­‐look  
Here’s the creamy
controller; it lives in
the middle

1 2
The user did something Change your state
Controller
3
Change your display
4
I’ve changed

View 5 Model
I need your state information Here’s the model; it
This is the user
handles all application
interface
data and logic

FEUP ● Nuno Flores ●


203

Looking  at  MVC  with  pattern  eyes  


STRATEGY

The user did something Change your state


Controller

Change your display

COMPOSITE OBSERVER
I’ve changed

View Model
I need your state information

 Can  you  justify  why  is  this  so?  

FEUP ● Nuno Flores ●


204

102
9/22/11

Observer  in  Model-­‐View-­‐Controller  

OBSERVER
Observers

My state has
Observable changed!

View

View
Model

All these observers will be


Controller notified whenever state
I’d like to register
changes in the model
as an observer

View The model has no dependencies


Any object that’s interested in state on viewers or controllers!
changed in the model registers
with the model as an observer.

FEUP ● Nuno Flores ●


205

Strategy  in  Model-­‐View-­‐Controller  

STRATEGY
The user did The controller is the strategy
something for the view - it’s the object
that knows how to handle
user actions.

The view delegates to


Controller
the controller to handle
the user actions.
We can swap in another
View behaviour for the view by
changing the controller
The view only worries about presentation, the controller
worries about translating user input to actions on the model. Controller

FEUP ● Nuno Flores ●


206

103
9/22/11

View  in  Model-­‐View-­‐Controller  

COMPOSITE paint()

Form Title

Enter Text

OK
View

The view is a composite of GUI Status bar


elements (labels, buttons, textboxes,
…)

FEUP ● Nuno Flores ●


207

Final  Quiz  
 30  minutes…GO!  

FEUP ● Nuno Flores ●


208

104
9/22/11

Final  Challenge  
 Pretende-­‐se  desenhar  uma  aplicação  de  GPS.  
• O  GPS  deve  apresentar  um  conjuntos  de  elementos  gráficos  que  
representem  os  elementos  reais,  e  que  se  compõem  uns  com  os  
outros.    
• Deves  actualizar  periodicamente  o  seu  display  há  medida  que  o  tempo  
passa  com  dados  do  satélite.  
• Deve  poder  comunicar  com  outros  dispositivos  para,  sendo  que  estes  
devem  apenas  aceder  ao  determinada  informação  do  GPS  
• Ao  ligar,  o  dispositivo  GPS  deve  verificar  se  existem  satélites,  se  
existem  3  ou  mais  começa  a  actualizar-­‐se,  se  existem  2  ou  menos  
tenta  ligar-­‐se  a  outros  dispositivos  GPS  próximos  a  tentar  captar  mais  
informação  relevante,  se  não  houver  satelite  nenhum,  desliga-­‐se.  
Quando  está  desligado,  mantém  sempre  uma  luz  de  presença.  
• Deve  ser  possível  mostrar  a  informação  segundo  várias  vistas  
diferentes  (texto,  2D,  3D).  
• Deve  conseguir  interagir  com  a  API  de  dispositivos  similares  de  outros  
fabricantes.  
FEUP ● Nuno Flores ●
209

Design  Pattern  defined…  


 A  Pattern  is  a  solution  to  a  problem  in  a  context.  
• context  
-­‐ the  situation  in  which  the  pattern  applies.    
-­‐ This  should  be  recurring.  
• problem  
-­‐ the  goal  you  are  trying  to  achieve  (in  this  context)  
-­‐ Also  refers  to  the  any  constraints  that  occur  (in  the  context)  
• solution  
-­‐ what  you’re  after  :  a  general  design  that  anyone  can  apply  which  resolves  the  goal  
and  the  set  of  constraints.  

 So…  
• Problem:  How  do  I  get  to  work  in  time?  
• Context:  I’ve  locked  my  keys  in  my  car.  
• Solution:  Break  the  window,  get  in  the  car,  start  the  engine  and  drive  to  work.  
(time  and  distance  constraints  resolved!)  
• Is  this  a  pattern?  
-­‐ Missing  “recurring”  
-­‐ Missing  constraint  “cost”  
-­‐ It  is  not  a  GOOD,  EXPERIENCED  and  COST-­‐EFFECTIVE  solution.  
-­‐ Its  missing  a  NAME!  

FEUP ● Nuno Flores ●


210

105
9/22/11

How  to  read  a  Design  Patterns  catalog  (I)  


 Name  (top  left  side)  
• All  patterns  ina  catalog  start  with  a  name  
• Without  a  good  name,  a  pattern  fails  to  make  the  “lingo”  

 Pattern  Classification  (top  right  side)  


• Patterns  can  be  classified  in  categories  (more  on  this  later…)  

 Also  Known  as  


• Alternative  names  for  the  same  pattern  (ussually  different  cant  for  the  
same  lingo)  

 Intent  
• What  the  pattern  does  in  a  short  statement  (the  post-­‐its!!!)  
• Pattern  definition,  its  “abstract”.  

 Motivation  
• Concrete  scenario  that  describes  the  problem  and  how  the  solution  
solves  the  problem.  
FEUP ● Nuno Flores ●
211

How  to  read  a  Design  Patterns  catalog  (II)  


 Applicability  
• Describes  situations  in  which  the  pattern  can  be  applied.  

 Structure  
• Provides  a  diagram  illustrating  the  relationships  among  classes  that  
participate  in  the  pattern  (as  the  ones  in  the  design  billboard).  

 Participants  
• Describes  the  responsibilities  and  roles  of  the  classes  and  objects  in  
the  design.  

 Collaborations  
• How  the  participants  work  together  in  the  pattern.  

 Consequences  
• Effects  that  using  this  patterns  may  have:  good  and  bad.  

 
FEUP ● Nuno Flores ●
212

106
9/22/11

How  to  read  a  Design  Patterns  catalog  (III)  


 Implementation/  Sample  Code  
• Provides  techniques  you  need  to  use  when  implementing  this  pattern,  
and  issues  you  should  watch  for.  
• Provides  code  fragments  that  might  help  with  implementation.  

 Knows  Uses  
• Describes  examples  of  this  pattern  found  in  real  systems.  

 Related  Patterns  
• Describes  the  relationship  between  this  pattern  and  the  others.  

 www.fe.up.pt/~aaguiar/as/gof  

FEUP ● Nuno Flores ●


213

So  you  wanna  be  a  Design  Patterns  writer  


 Do  your  homework.  
• Be  well  versed  in  the  existing  patterns.  
• New  patters  may  be  variants  of  old  patterns.  

 Take  time  to  reflect,  evaluate.  


• Medidate  on  your  experience,  and  try  to  find  recurrent  designs.  
• May  be  there  is,  somewhere,  an  already  found  pattern.  

 Get  your  ideias  down  on  a  paper  in  a  way  other  can  understand.  
• Must  be  easy  to  read  and  understand.  Provides  feedback  to  your  design.  
• Use  the  template  of  catalogs.  It  has  to  make  sense  for  others.  

 Have  other  try  your  pattern;  then  refine  some  more.  


• Think  of  your  pattern  as  a  work  in  progress.  
• Incorporate  feedback  into  your  pattern.  

 Don’t  forget  the  rule  of  three.  


• Unless  your  pattern  has  been  successfully  applied  to  three  real-­‐world  solutions,  
it  can’t  qualify  as  a  a  pattern.  

FEUP ● Nuno Flores ●


214

107
9/22/11

Organizing  Design  Patterns  


 Three  categories  
• Creational  
-­‐ Involve  object  instantiation  and  all  provide  a  way  to  decouple  a  client  form  
objects  it  needs  to  instantiate.  
-­‐ SINGLETON,  ABSTRACT  FACTORY,  FACTORY  METHOD,  BUILDER,  
PROTOTYPE  
• Behavioral  
-­‐ Concerns  how  classes  and  objects  interact  and  distribute  responsibility  
-­‐ STRATEGY,  TEMPLATE  METHOD,  COMMAND,  STATE,  ITERATOR,  
OBSERVER,  INTERPRETER,  MEMENTO,  MEDIATOR,  VISITOR,  CHAIN  OF  
RESPONSIBILITY  
• Structural  
-­‐ Let  you  compose  classes  or  objects  into  larger  structures  
-­‐ COMPOSITE,  DECORATOR,  FACADE,  ADAPTER,  PROXY,  BRIDGE,  
FLYWEIGHT.  

FEUP ● Nuno Flores ●


215

Thinking  in  Patterns  


 Keep  it  simple  (KISS)  
• Goal:  Simplicity.  A  pattern  may  introduce  too  much  complexity  for  the  gain  in  
flexibility  
• But,  sometimes,  the  best  way  to  keep  it  simple  and  flexible  is  a  DP.  

 Design  Patterns  aren’t  a  magic  bullet  


• In  fact,  they  are  not  even  a  bullet.  
• Use  patterns,  conscient  of  the  consequences…  

 You  know  you  need  a  pattern  when…  


• The  BIG  QUESTION…(more  on  this  on  next  slide)  

 Refactoring  time  is  Patterns  time!  


• Reexamine  your  design  to  see  if  a  pattern  doesn’t  make  it  more  structured.  

 Take  out  a  DPs  if  you  don’t  really  need  it!  


• A  simpler  solution  without  a  pattern  could  be  better.  

 If  you  don’t  need  it  now,  don’t  do  it  now.  


• DPs  are  beautiful,  but  resist  the  temptation…  
FEUP ● Nuno Flores ●
216

108
9/22/11

Anti-­‐Patterns  
 An  AntiPattern  is  a  pattern  that  tells  how  to  go  from  a  
problem  to  a  bad  solution.    
• Identifying  bad  practices  can  be  as  valuable  as  identifying  good  
practices.    
• Tells  you  why  the  bad  solution  looks  attractive.  
• Why  it  turns  out  to  be  bad.  
• What  positive  patterns  are  applicable  in  its  stead.    

 Some  repeated  pattern  of  action,  process  or  structure  that  


initially  appears  to  be  beneficial,  but  ultimately  produces  
more  bad  consequences  than  beneficial  results.  

FEUP ● Nuno Flores ●


217

“CopyAndPasteProgramming”  
 Problem:  Reusing  code  with  a  minimum  of  effort.    
 Context:  Trying  to  optimize  reuse  when  maintaining  an  existing  system.    
 Forces:  Design-­‐time  reuse  is  a  lot  of  work.  If  a  system  has  already  been  implemented,  the  
reusable  assets  are  there  for  the  picking.  During  maintenance,  you  often  do  not  know  the  
assumptions  that  a  module  is  making,  so  changing  it  is  risky.  It  is  safer  to  add  new  code  than  to  
change  old  code.  Restructuring  existing  code  to  be  more  reusable  (called  ReFactoring  by  Opdyke  
et  al.  [1])  is  expensive,  particularly  if  the  system  is  large.    
 Supposed  Solution:  Minimize  reuse  costs  by  cloning  code  and  modifying  it  to  suit  new  contexts.    
 Resulting  Context:  Reuse  is  easy,  though  specific  blocks  of  reusable  code  are  duplicated  across  
the  source  spectrum.  Individual  bug  fixes  or  enhancements  to  the  original  source  must  be  
individually  ported  to  all  clones  if  and  when  they  can  be  tracked  down.    
 Design  Rationale:  Short-­‐term  pay-­‐off  is  more  easily  justified  than  a  boondoggle  that  promises  
long-­‐term  investment  without  any  conclusive  proof.    
 Appropriate  Usage:  If  the  copies  of  the  code  will  be  heavily  modified,  it  can  be  better  to  have  the  
separate  copies  so  that  each  can  be  changed  independently.  Later  CodeHarvesting  eliminates  
redundancy  after  the  finer  points  have  been  worked  out.  It  can  also  be  handy  to  have  two  
variants  of  a  piece  of  code  when  debugging  one  variant  only,  setting  breakpoints  in  the  variant  of  
interest.    
 Synonyms:  CloneAndModifyProgramming,  SnarfAndBarfProgramming,  ClipboardInheritance?,  
ClipboardCoding?,  RapeAndPasteProgramming    

FEUP ● Nuno Flores ●


218

109
9/22/11

Your  Mind  on  Patterns  


 Beginner  Mind  
• The  Beginner  uses  patterns  everywhere  
• “I  need  a  pattern  for  Hello  World”  

 Intermediate  Mind  
• As  the  learning  progresses,  the  Intermediate  mind  starts  to  see  where  
patterns  are  needed  and  where  they  aren’t  
• “Maybe  I  need  a  Singleton  here”  

 Zen  Mind  
• The  Zen  Mind  is  able  to  see  patterns  where  they  fit  naturally.  
• “This  is  a  natural  place  for  Decorator”  

FEUP ● Nuno Flores ●


219

Better  places  to  use  your  vocabulary  


 Design  meetings  
 With  other  developers  
 In  architecture  documentation  
 In  code  comments  and  naming  conventions  
 To  groups  of  interested  developers  

FEUP ● Nuno Flores ●


220

110
9/22/11

Your  journey  has  just  begun  


 Gof  Book  
 Design  Patterns  catalogs  
• Just  google:  “Design  patterns  catalogs”  
• Most  popular  
-­‐ San  Francisco  patterns  catalog  
-­‐ Patterns  Almanac  

 Websites  
• Portland  Patterns  Repository  
-­‐ http://c2.com  
• Hillside  Group  
-­‐ http://hillside.net  

 Conferences  and  workshops  


• OOPSLA  
• PLOP  
• Viking  PLOP  
• ECOOP  
• ...  

FEUP ● Nuno Flores ●


221

Leftover  patterns  
 BRIDGE  
• Decouple  an  abstraction  from  its  implementation  so  that  the  two  can  vary  
independently.  

 BUILDER  
• Separates  the  construction  of  a  complex  object  from  its  representation  so  that  
the  same  construction  process  can  create  different  representations  

 CHAIN  OF  RESPONSIBILITY  


• Avoid  coupling  the  sender  of  a  request  to  its  receiver  by  giving  more  than  one  
object  change  to  handle  the  request.  Chain  the  receiveing  objects  and  pass  the  
request  along  the  chain  until  an  object  handles  it.  

 FLYWEIGHT  
• Use  sharing  to  support  large  numbers  of  fine-­‐grained  objects  efficiently.  

 INTERPRETER  
• Given  a  language,  define  a  representation  for  its  grammar  along  with  an  
interpreter  that  uses  the  representation  to  interpret  sentences  in  the  language.  

FEUP ● Nuno Flores ●


222

111
9/22/11

Leftover  patterns  
 MEDIATOR  
• Define  an  object  that  encapsulates  how  a  set  of  objects  interact.  
Promotes  loose  coupling  by  keeping  objects  from  referring  to  each  
other  explicitly,  and  its  lets  yo  vary  their  interaction  dependently.  

 MEMENTO  
• Without  violating  encapsulation,  capture  and  externalize  an  object’s  
internal  state  so  that  the  object  can  be  restored  to  this  stage  later.  

 PROTOTYPE  
• Specify  the  kinds  of  objects  to  create  using  a  prototypical  instance,  
and  create  new  objects  by  copying  this  prototype.  

 VISITOR  
• Represent  an  operation  to  be  performed  on  the  elements  of  an  object  
structure.  Lets  you  define  a  new  operation  without  changing  the  
classes  of  the  elements  on  which  it  operates.  

FEUP ● Nuno Flores ●


223

And  it  goes  on,  and  on,  and  on…  


 Thank  you,  I  hope  you  enjoyed  it…  

FEUP ● Nuno Flores ●


224

112

You might also like