design pattern 2 [ff 6 – 11]. remember starbuzz coffee? 2 coffee instruction 1.boil water 2.brew...
TRANSCRIPT
![Page 1: Design Pattern 2 [FF 6 – 11]. Remember Starbuzz Coffee? 2 Coffee instruction 1.Boil water 2.Brew coffee in boiling water 3.Pour the mix in cup 4.Add sugar](https://reader035.vdocument.in/reader035/viewer/2022062713/56649cf55503460f949c4c20/html5/thumbnails/1.jpg)
Design Pattern 2[FF 6 – 11]
![Page 2: Design Pattern 2 [FF 6 – 11]. Remember Starbuzz Coffee? 2 Coffee instruction 1.Boil water 2.Brew coffee in boiling water 3.Pour the mix in cup 4.Add sugar](https://reader035.vdocument.in/reader035/viewer/2022062713/56649cf55503460f949c4c20/html5/thumbnails/2.jpg)
2
Remember Starbuzz Coffee?
Coffee instruction1. Boil water2. Brew coffee in boiling water3. Pour the mix in cup4. Add sugar and milk
Tea instruction1. Boil water2. Put tea leaves in boiling water3. Pour the mix in cup4. Add lemon
CoffeeboilWater()brewCoffee() pourMix()addSugarMilk()prepare()
TeaboilWater()brewTea() pourMix()addLemon()prepare()
prepare() { boilWater() brewCoffee() pourMix() addSugarMilk()}
Can we improve this design?
![Page 3: Design Pattern 2 [FF 6 – 11]. Remember Starbuzz Coffee? 2 Coffee instruction 1.Boil water 2.Brew coffee in boiling water 3.Pour the mix in cup 4.Add sugar](https://reader035.vdocument.in/reader035/viewer/2022062713/56649cf55503460f949c4c20/html5/thumbnails/3.jpg)
3
Factor out common things to a superclass
CoffeebrewCoffee() addSugarMilk()prepare()
TeabrewTea() addLemon()prepare()
<<abstract>>HotBeverageboilWater()pourMix()prepare() // abs
prepare() { boilWater() brewCoffee() pourMix() addSugarMilk()}
prepare() { boilWater() brewTea() pourMix() addLemon()}
What else can be improved?
prepare() { boilWater() brew () pourMix() addCondiments()}
you can even finalize it
![Page 4: Design Pattern 2 [FF 6 – 11]. Remember Starbuzz Coffee? 2 Coffee instruction 1.Boil water 2.Brew coffee in boiling water 3.Pour the mix in cup 4.Add sugar](https://reader035.vdocument.in/reader035/viewer/2022062713/56649cf55503460f949c4c20/html5/thumbnails/4.jpg)
4
The new design
Coffeebrew() addCondiments ()
Teabrew() addCondiments()
<<abstract>>HotBeverageboilWater()pourMix()prepare()brew()addCondiments()
“prepare” is no longer
abstract!
final prepare() { boilWater() brew () pourMix() addCondiments()}
So how easy is it now to add Chocolate??
The method “prepare” is a so-called “template method”; “brew” and “addCondiments” are called “hooks”. So this “pattern” here is called “Template Method Pattern”.
![Page 5: Design Pattern 2 [FF 6 – 11]. Remember Starbuzz Coffee? 2 Coffee instruction 1.Boil water 2.Brew coffee in boiling water 3.Pour the mix in cup 4.Add sugar](https://reader035.vdocument.in/reader035/viewer/2022062713/56649cf55503460f949c4c20/html5/thumbnails/5.jpg)
5
Another example
public class MyApplet extends Applet {
public void init() { start to pre-load that film! load main image repaint() }
public void stop() { if film is playing, stop it }
public void start() { continue film }
public void paint() {...}}
These are hooks, used by a number of template methods in the superclass Applet.
![Page 6: Design Pattern 2 [FF 6 – 11]. Remember Starbuzz Coffee? 2 Coffee instruction 1.Boil water 2.Brew coffee in boiling water 3.Pour the mix in cup 4.Add sugar](https://reader035.vdocument.in/reader035/viewer/2022062713/56649cf55503460f949c4c20/html5/thumbnails/6.jpg)
6
Generic remote control
• We need to design this generic RC for HomeAutomation Inc• Slots must be dynamically assignable• HA provides a bunch of “devices”• Unfortunately they have varying interface• Furthermore ... expect more devices will come in the future
RemoteControlslots : Device[8]assignSlot(slotNr,device)turnOn(slotNr)turnOff(slotNr)undo()
OutdoorLightturnOn()turnOff()
StereoturnOn()putcd()setvolume(v)turnOff()
CeilingFanlow()medium()high()off()getSpeed()
Device
![Page 7: Design Pattern 2 [FF 6 – 11]. Remember Starbuzz Coffee? 2 Coffee instruction 1.Boil water 2.Brew coffee in boiling water 3.Pour the mix in cup 4.Add sugar](https://reader035.vdocument.in/reader035/viewer/2022062713/56649cf55503460f949c4c20/html5/thumbnails/7.jpg)
7
First solution
• Behavior that dynamically depends on subtypes• Remember the Factory solution ?• We need to do something similar, but with dynamic behavior
selection. • (this presentation deviates a bit from FF)
RemoteControlslot : Device[8]assignSlot(slotNr,device)turnOn(slotNr)turnOff(slotNr)undo()
turnOn(n) { d = slot[n] if d is an OutdoorLight then d.turnOn() else if d is a Stereo then { d.turnOn() d.putCD() d.setVolume(10) } else ...}
![Page 8: Design Pattern 2 [FF 6 – 11]. Remember Starbuzz Coffee? 2 Coffee instruction 1.Boil water 2.Brew coffee in boiling water 3.Pour the mix in cup 4.Add sugar](https://reader035.vdocument.in/reader035/viewer/2022062713/56649cf55503460f949c4c20/html5/thumbnails/8.jpg)
8
Encapsulating ...
We encapsulate each “sub-type” of behavior in its own “Command” class.
RemoteControlonCmds : Command[8]offCmds : Command[8] assignSlot(slotNr,device)turnOn(slotNr)turnOff(slotNr)undo()
Device LightOnCmd
Commandexecute()
LightOffCmd
StrereoOnCmd
StrereoOffCmd
our “behavior factory method” :
assignSlot(n,device) { onCmds[n] = device.createOnCmd() ; offCmds[n] = device.createOffCmd() ; }
turnOn(n) { onCmds[n].execute() }
turnOff(n) { offCmds[n].execute() }
![Page 9: Design Pattern 2 [FF 6 – 11]. Remember Starbuzz Coffee? 2 Coffee instruction 1.Boil water 2.Brew coffee in boiling water 3.Pour the mix in cup 4.Add sugar](https://reader035.vdocument.in/reader035/viewer/2022062713/56649cf55503460f949c4c20/html5/thumbnails/9.jpg)
9
How client requests are now handled..
DeviceOutdoorLightOnCmd
Commandexecute()
OutdoorLightOffCmd
StrereoOnCmd
StrereoOffCmdexecute() { d = (Strereo) device d.turnOn() ; d.putCD() ; d.setVolume(10)}
execute() { d = (OutdoorLight) device d.turnOn() ;}
:RC
turnOn(1)execute() turnOn()
putCD()setVolume(10)
:Command :Device
OutdoorLightOnCmd OutdoorLight
![Page 10: Design Pattern 2 [FF 6 – 11]. Remember Starbuzz Coffee? 2 Coffee instruction 1.Boil water 2.Brew coffee in boiling water 3.Pour the mix in cup 4.Add sugar](https://reader035.vdocument.in/reader035/viewer/2022062713/56649cf55503460f949c4c20/html5/thumbnails/10.jpg)
10
Adding Fan-commands and Undo
DeviceOutdoorLightOnCmd
Commandexecute()undo()
OutdoorLightOffCmd
FanOnCmd
FunOffCmd
execute() { d = (CeilingFan) device speed = d.getSpeed() if speed is 0 then d.low() else if speed is low then d.medium() … oldstate = speed}
undo() { (OutdoorLight) device . turnOff() }
FanCmdoldState
undo() { d = (CeilingFan) device if oldstate is off then d.turnOff() else if oldstate is low then d.low() ... }
![Page 11: Design Pattern 2 [FF 6 – 11]. Remember Starbuzz Coffee? 2 Coffee instruction 1.Boil water 2.Brew coffee in boiling water 3.Pour the mix in cup 4.Add sugar](https://reader035.vdocument.in/reader035/viewer/2022062713/56649cf55503460f949c4c20/html5/thumbnails/11.jpg)
11
Now implementing “undo” on the RC ...
RemoteControlonCmds : Command[8]offCmds : Command[8] assignSlot(slotNr,device)turnOn(slotNr)turnOff(slotNr)undo()- lastCmd : Command
turnOn(n) { c = onCmds[n] c.execute() lastCmd = c}
undo() { lastCmd.undo() lastCmd = new DoNothingDevice()}
![Page 12: Design Pattern 2 [FF 6 – 11]. Remember Starbuzz Coffee? 2 Coffee instruction 1.Boil water 2.Brew coffee in boiling water 3.Pour the mix in cup 4.Add sugar](https://reader035.vdocument.in/reader035/viewer/2022062713/56649cf55503460f949c4c20/html5/thumbnails/12.jpg)
12
The “Command Pattern”
Receiveroperation1operation2
Concrete Cmd 1<<interface>>Commandexecute()undo() Concrete Cmd 2
Invoker
Client
<<create>>
Device
RemoteControl
Encapsulate behavior as an object; like normal object, these objects can be e.g. grouped together, send, and manipulated, before we execute the behavior they represent.
(different formulation than FF)
Device
![Page 13: Design Pattern 2 [FF 6 – 11]. Remember Starbuzz Coffee? 2 Coffee instruction 1.Boil water 2.Brew coffee in boiling water 3.Pour the mix in cup 4.Add sugar](https://reader035.vdocument.in/reader035/viewer/2022062713/56649cf55503460f949c4c20/html5/thumbnails/13.jpg)
13
Example of things you can do
• You can stream commands, and have multiple threads consuming them
• logging and reload useful when the “invoker” crashes
MacroCmdcmds : Command[]execute()undo()
execute() { for (i=0; i<#cmds; i++) cmds[i].execute()}
undo() { for (i=#cmds; 0<i; i--) cmds[i-1].undo()}
![Page 14: Design Pattern 2 [FF 6 – 11]. Remember Starbuzz Coffee? 2 Coffee instruction 1.Boil water 2.Brew coffee in boiling water 3.Pour the mix in cup 4.Add sugar](https://reader035.vdocument.in/reader035/viewer/2022062713/56649cf55503460f949c4c20/html5/thumbnails/14.jpg)
14
The merging of 3 restaurants...
• They can agree on a common class for “menu item”• But refuse to change how the menus are internally represented too
much of their respective software already depend on it
MenuItemnamedescisVeggieprice
DinnerMenumenu : MenuItem[]addItem(item)
PancakeHouseMenumenu : ArrayListaddItem(item)
CafeMenumenu : HashTableaddItem(item)
MenuWebInterfaceprintFullMenu()printVeggies()printLowBudget()
*
*
*(“Waitress” in your book)
![Page 15: Design Pattern 2 [FF 6 – 11]. Remember Starbuzz Coffee? 2 Coffee instruction 1.Boil water 2.Brew coffee in boiling water 3.Pour the mix in cup 4.Add sugar](https://reader035.vdocument.in/reader035/viewer/2022062713/56649cf55503460f949c4c20/html5/thumbnails/15.jpg)
15
Let’s now implement the MenuWebInterface …
printFullMenu() { dinnerItems = dinnerMenu.items // array for (i=0; i<dinnerItems.size; i++) print (dinnerItem[i]) lunchItems = pancakeHouseMenu.items // listarray for (i=0; i<lunchItems.size(); i++) print ((MenuItem) lunchItems.get(i))
drinks = cafeMenu.items.getValues() // values of hash-table for (i=0; i<drinks.size(); i++) print ((MenuItem) drinks.get(i))}
Similar iterations in implementing the other print operations
![Page 16: Design Pattern 2 [FF 6 – 11]. Remember Starbuzz Coffee? 2 Coffee instruction 1.Boil water 2.Brew coffee in boiling water 3.Pour the mix in cup 4.Add sugar](https://reader035.vdocument.in/reader035/viewer/2022062713/56649cf55503460f949c4c20/html5/thumbnails/16.jpg)
16
Encapsulating iterationsDinnerMenu- menu : MenuItem[]addItem(item)
PancakeHouseMenu- menu : ArrayListaddItem(item)
<<interface>>IteratorhasNext() : boolnext() : Object
MenugetName()createIterator()
<<create>>
(deviate a bit from FF)
// you can hide it now
DinnerMenuIterator
PancakeMenuIterator class DinnerMenuIterator extends Iterator { MenuItem[] items int ctr
DinnerMenuIterator(items) { this.items = items ; ctr = -1 }
hasNext() { return ctr < #items - 1 } next() { ctr++ ; return items[ctr] }}
createIterator() { return new DinnerMenuIterator(menu)}
Iterator pattern
(abs. class)
![Page 17: Design Pattern 2 [FF 6 – 11]. Remember Starbuzz Coffee? 2 Coffee instruction 1.Boil water 2.Brew coffee in boiling water 3.Pour the mix in cup 4.Add sugar](https://reader035.vdocument.in/reader035/viewer/2022062713/56649cf55503460f949c4c20/html5/thumbnails/17.jpg)
17
Reworking MenuWebInterfaceMenuWI
<<interface>>MenugetName()createIterator()
* menus
printMenu() { for (Menu m : menus) { print m.getName() iter = m.getIterator() while (iter.hasNext()) { i = (MenuItem) iter.next() ; print(i) ; }}
: MenuWI : DinnerMenu
: DinnerMenuIterator
printMenu()createIterator() <<create>>
hasNext()
next()
etc …
![Page 18: Design Pattern 2 [FF 6 – 11]. Remember Starbuzz Coffee? 2 Coffee instruction 1.Boil water 2.Brew coffee in boiling water 3.Pour the mix in cup 4.Add sugar](https://reader035.vdocument.in/reader035/viewer/2022062713/56649cf55503460f949c4c20/html5/thumbnails/18.jpg)
18
Iterator in Java
• Using the pattern amounts to subclass it• Standard collection classes already come with their iterator-classes.• “remove” is optional. It removes the element the element you just get from next() ; can
only be called once per next() call.• if you change the underlying ‘collection’ during an iteration by any other way than using
remove(), the behavior of the Iterator is undefined.
<<interface>>IteratorhasNext() : boolnext() : Objectremove() : void
Java.Util.Interface
i = V.iterator() ;while (i.hasNext()) { x = i.next() ; if (x == Bob) V.add(Patrick) ; print(x) ;}
// will Patrick be printed ?
![Page 19: Design Pattern 2 [FF 6 – 11]. Remember Starbuzz Coffee? 2 Coffee instruction 1.Boil water 2.Brew coffee in boiling water 3.Pour the mix in cup 4.Add sugar](https://reader035.vdocument.in/reader035/viewer/2022062713/56649cf55503460f949c4c20/html5/thumbnails/19.jpg)
19
While we are talking about Java iterators...
<<interface>>IteratorhasNext() : boolnext() : Objectremove() : void
<<interface>>EnumerationhasMoreElements() : boolnextElement() : Object
Before Java 1.2 :
Suppose we have Java 1.1 legacy code; new features are to be added in 1.6. In the new part we prefer to use Iterator; but how to upgrade your old Enumeration classes to Iterators?
EnumerationAdapterconstructor(enumeration)
1.6Client
<<use>>1
Concrete EnumerationA
![Page 20: Design Pattern 2 [FF 6 – 11]. Remember Starbuzz Coffee? 2 Coffee instruction 1.Boil water 2.Brew coffee in boiling water 3.Pour the mix in cup 4.Add sugar](https://reader035.vdocument.in/reader035/viewer/2022062713/56649cf55503460f949c4c20/html5/thumbnails/20.jpg)
20
Implementation
<<interface>>IteratorhasNext() : boolnext() : Objectremove() : void
<<interface>>EnumerationhasMoreElements() : boolnextElement() : Object
EnumerationAdapterenumconstructor(enumeration)
1.6Client
<<use>>1
Concrete EnumerationA
EnumerationAdapter(e) { enum = e }
enum
hasNext() { return enum.hasMoreElements() }next() { return enum.nextElement() }remove() ...??
For client now to iterate over A :
e = instanceA.getEnum()i = new EnumerationAdapter(e)
AgetEnum() : ConcreteEnumerationA
![Page 21: Design Pattern 2 [FF 6 – 11]. Remember Starbuzz Coffee? 2 Coffee instruction 1.Boil water 2.Brew coffee in boiling water 3.Pour the mix in cup 4.Add sugar](https://reader035.vdocument.in/reader035/viewer/2022062713/56649cf55503460f949c4c20/html5/thumbnails/21.jpg)
21
That was the “adapter pattern”
Targetoperations
Adapteeother operations
Adapter
Client<<use>>
1
Iterator
Enumeration
• We’ll discuss two more variants: Proxy and Facade.• Not too complicated
![Page 22: Design Pattern 2 [FF 6 – 11]. Remember Starbuzz Coffee? 2 Coffee instruction 1.Boil water 2.Brew coffee in boiling water 3.Pour the mix in cup 4.Add sugar](https://reader035.vdocument.in/reader035/viewer/2022062713/56649cf55503460f949c4c20/html5/thumbnails/22.jpg)
22
Adding a reporting function to parking machines
ParkingMachinelocation()count()hours()
Report+ printReport ()
printReport() { for (Machine m : machines) { print m.location() print m.count() print m.hours() }}
machines
Does not work if the parking machines objects exist on physically different computers.
We need a networking solution, but want a nice way to fit that into our design.
*
![Page 23: Design Pattern 2 [FF 6 – 11]. Remember Starbuzz Coffee? 2 Coffee instruction 1.Boil water 2.Brew coffee in boiling water 3.Pour the mix in cup 4.Add sugar](https://reader035.vdocument.in/reader035/viewer/2022062713/56649cf55503460f949c4c20/html5/thumbnails/23.jpg)
23
Proxy pattern
Report+ printReport ()
ParkingMachinelocation()count()hours()
<<interface>>ParkingMachineInterfacelocation()count()hours()
ParkingMachine
ParkingMachineProxy
client sideremote side
The proxy pass requests to the actual subject; implying it implements this passing mechanism, e.g. over Internet
Create a “stand-in” for another object; useful when the real object is remote, or expensive to create, or require securing.
subject
real subject
*
![Page 24: Design Pattern 2 [FF 6 – 11]. Remember Starbuzz Coffee? 2 Coffee instruction 1.Boil water 2.Brew coffee in boiling water 3.Pour the mix in cup 4.Add sugar](https://reader035.vdocument.in/reader035/viewer/2022062713/56649cf55503460f949c4c20/html5/thumbnails/24.jpg)
24
Home cinema
![Page 25: Design Pattern 2 [FF 6 – 11]. Remember Starbuzz Coffee? 2 Coffee instruction 1.Boil water 2.Brew coffee in boiling water 3.Pour the mix in cup 4.Add sugar](https://reader035.vdocument.in/reader035/viewer/2022062713/56649cf55503460f949c4c20/html5/thumbnails/25.jpg)
25
Ok.. let’s watch a film now
• Complicated...• How about when we are
done watching film.• How about listening to
music? etc• What if we upgrade the
system?
![Page 26: Design Pattern 2 [FF 6 – 11]. Remember Starbuzz Coffee? 2 Coffee instruction 1.Boil water 2.Brew coffee in boiling water 3.Pour the mix in cup 4.Add sugar](https://reader035.vdocument.in/reader035/viewer/2022062713/56649cf55503460f949c4c20/html5/thumbnails/26.jpg)
26
Facade pattern
To provide a simplified interface.
HomeCinemaFacedewatchFilm()listenCD()
Client<<use>>
So... can you say when it is more appropriate to use one of these over the other ?• Adapter• Proxy• Facade• Decorator
![Page 27: Design Pattern 2 [FF 6 – 11]. Remember Starbuzz Coffee? 2 Coffee instruction 1.Boil water 2.Brew coffee in boiling water 3.Pour the mix in cup 4.Add sugar](https://reader035.vdocument.in/reader035/viewer/2022062713/56649cf55503460f949c4c20/html5/thumbnails/27.jpg)
27
Candy machine…
no coin
has coin
sold
empty
inse
rt co
in
turn crank
/ [counter is updated]
[not empty]
[empty]
CandyMachine- state+ insertCoin(c)+ turnCrank()+ getCandy()
get candy
insert coin
turn crank
get candy[1eur]
[else
] / [
coin
is e
ject
ed]
![Page 28: Design Pattern 2 [FF 6 – 11]. Remember Starbuzz Coffee? 2 Coffee instruction 1.Boil water 2.Brew coffee in boiling water 3.Pour the mix in cup 4.Add sugar](https://reader035.vdocument.in/reader035/viewer/2022062713/56649cf55503460f949c4c20/html5/thumbnails/28.jpg)
28
Mapping this to implementation
class CandyMachine { static final NOCOIN = 0 static final HASCOIN = 1 static final SOLD = 2 static final EMPTY = 3
private state private n
CandyMachine() { this.n = 200 state = NOCOIN }}
insertcoin(c) { if (state == NOCOIN) { if (c is 1 euro) state = HASCOIN else eject c } else eject c}
getcandy() { if (state == SOLD) { n-- if (n==0) state = EMPTY else state = NOCOIN } else skip}
![Page 29: Design Pattern 2 [FF 6 – 11]. Remember Starbuzz Coffee? 2 Coffee instruction 1.Boil water 2.Brew coffee in boiling water 3.Pour the mix in cup 4.Add sugar](https://reader035.vdocument.in/reader035/viewer/2022062713/56649cf55503460f949c4c20/html5/thumbnails/29.jpg)
29
The company wants to add usr messaging
insertcoin(c) { if (state == NOCOIN) { if (c is 1 euro) state = HASCOIN else { print “Not 1 euro” eject c } } else if (state == HASCOIN || state == SOLD) { print “You have inserted a coin” eject c } else if (state == EMPTY) { print “the machine is empty” eject c }}
getcandy() { if (state == SOLD) { if (n==0) state = EMPTY else state = NOCOIN } else if (state == NOCOIN) print “You have not inserted a coin” else if (state == HASCOIN) print “You =have not turned the crank” …}
![Page 30: Design Pattern 2 [FF 6 – 11]. Remember Starbuzz Coffee? 2 Coffee instruction 1.Boil water 2.Brew coffee in boiling water 3.Pour the mix in cup 4.Add sugar](https://reader035.vdocument.in/reader035/viewer/2022062713/56649cf55503460f949c4c20/html5/thumbnails/30.jpg)
30
The company wants to add prize ball!
no coin
has coin
sold
empty
inse
rt co
in
turn crank
/ [counter is updated]
[not empty]
[empty]
get candy
[1eur]
[else
] / [
coin
is e
ject
ed]
bonus
get candy
turn crank[n>1]
/ [counter is updated]
Implementationblows!
turn crank
/ [counter is updated]
![Page 31: Design Pattern 2 [FF 6 – 11]. Remember Starbuzz Coffee? 2 Coffee instruction 1.Boil water 2.Brew coffee in boiling water 3.Pour the mix in cup 4.Add sugar](https://reader035.vdocument.in/reader035/viewer/2022062713/56649cf55503460f949c4c20/html5/thumbnails/31.jpg)
31
Encapsulating state
CMstateinsertCoin(c)turnCrank()getcandy()
NoCoinSt
HasCoinSt
SoldSt
EmptySt
candyMachine- n : int+ insertCoin(c)+ turnCrank()+ getcandy()
(current) state
1
owner
0..1
candyMachine() { n = 200 state = new NoCoin(this)}
NoCoinSt(machine) { owner = machine}
insertCoin(c) { state.insertCoin(c) }turnCrank() { state.turnCrank() }getcandy() { state.getcandy() }
Simple candy Machine !
(abstract class)
![Page 32: Design Pattern 2 [FF 6 – 11]. Remember Starbuzz Coffee? 2 Coffee instruction 1.Boil water 2.Brew coffee in boiling water 3.Pour the mix in cup 4.Add sugar](https://reader035.vdocument.in/reader035/viewer/2022062713/56649cf55503460f949c4c20/html5/thumbnails/32.jpg)
32
Implementing the states
CMstateinsertCoin(c)turnCrank()getcandy()
NoCoinSt
HasCoinStcandyMachine 1
owner
0..1 …
insertCoin(c) { if (c is 1 euro) owner.state = new HasCoinSt(owner) else { print “not 1 euro coin” ; eject c }}
insertCoin(c) { print “you have inserted a coin” ; eject c }}
getcandy() { print “you have not inserted a coin”}
getcandy() { print “you must first turn the crank” }}
insertcoin(c) { if (state == NOCOIN) { if (c is 1 euro) state = HASCOIN else { print “Not 1 euro” eject c } } else if (state == HASCOIN || state == SOLD) { print “You have inserted a coin” eject c } else if (state == EMPTY) { print “the machine is empty” eject c }}
getcandy() { if (state == SOLD) { if (n==0) state = EMPTY else state = NOCOIN } else if (state == NOCOIN) print “You have not inserted a coin” else if (state == HASCOIN) print “You =have not turned the crank” …}
![Page 33: Design Pattern 2 [FF 6 – 11]. Remember Starbuzz Coffee? 2 Coffee instruction 1.Boil water 2.Brew coffee in boiling water 3.Pour the mix in cup 4.Add sugar](https://reader035.vdocument.in/reader035/viewer/2022062713/56649cf55503460f949c4c20/html5/thumbnails/33.jpg)
33
What is the point of this?
CMstateinsertCoin(c)turnCrank()getcandy()
NoCoinSt
HasCoinSt
SoldSt
EmptySt
candyMachine- n : int+ insertCoin(c)+ turnCrank()+ getcandy()
(current) state
1
owner
0..1
BonusSt
What need to be done ?
• Obviously implement BonusSt this implements all arrows leaving Bonus• We still have to code incoming arrows turnCrank of HasCoinSt
The changes in the existing code is minimized!
![Page 34: Design Pattern 2 [FF 6 – 11]. Remember Starbuzz Coffee? 2 Coffee instruction 1.Boil water 2.Brew coffee in boiling water 3.Pour the mix in cup 4.Add sugar](https://reader035.vdocument.in/reader035/viewer/2022062713/56649cf55503460f949c4c20/html5/thumbnails/34.jpg)
34
State pattern
Extensible implementation of state-machine.(dev. from FF)
Stateoperation1(..)operation2(..)
Concrete State 1
Concrete State 2
StMachineoperation1(..)operation2(..)
(current) state
1
owner
0..1…
<<interface>>Statehandle(..)
Concrete State 1
Concrete State 2
Contextrequest(..)
…request(..) { state.handle(..) }
FF:
![Page 35: Design Pattern 2 [FF 6 – 11]. Remember Starbuzz Coffee? 2 Coffee instruction 1.Boil water 2.Brew coffee in boiling water 3.Pour the mix in cup 4.Add sugar](https://reader035.vdocument.in/reader035/viewer/2022062713/56649cf55503460f949c4c20/html5/thumbnails/35.jpg)
35
Back to our restaurants…
DinnerMenu
PancakeHouseMenuMenu
(deviate a bit from FF)
CafeMenuMenuItem
*
![Page 36: Design Pattern 2 [FF 6 – 11]. Remember Starbuzz Coffee? 2 Coffee instruction 1.Boil water 2.Brew coffee in boiling water 3.Pour the mix in cup 4.Add sugar](https://reader035.vdocument.in/reader035/viewer/2022062713/56649cf55503460f949c4c20/html5/thumbnails/36.jpg)
36
What if we plan to add submenus in the future?all menus
: DinnerMenu : PancakeMenu : CafeMenu
MenuItems
: Dessert Menu
We need a tree structure.And a convenient and extensible way to implement computations that traverse the tree, like:• Counting the menu items• Get the cheapest menu item• Checking if a menu item is present
![Page 37: Design Pattern 2 [FF 6 – 11]. Remember Starbuzz Coffee? 2 Coffee instruction 1.Boil water 2.Brew coffee in boiling water 3.Pour the mix in cup 4.Add sugar](https://reader035.vdocument.in/reader035/viewer/2022062713/56649cf55503460f949c4c20/html5/thumbnails/37.jpg)
37
Composite pattern
Componentoperation(..)add(component)remove(component) getChild(k)
Compositeoperation(..)add(component)remove(component) getChild(k) // or getChildren() .. or ret. iterator
Leafoperation(..)
* components
:Composite
:Composite:Leaf :Leaf
:Leaf :Leaf
:Composite
:Leaf :Leaf
(FF’s formulation of the pattern)
operation e.g. get all leaves
![Page 38: Design Pattern 2 [FF 6 – 11]. Remember Starbuzz Coffee? 2 Coffee instruction 1.Boil water 2.Brew coffee in boiling water 3.Pour the mix in cup 4.Add sugar](https://reader035.vdocument.in/reader035/viewer/2022062713/56649cf55503460f949c4c20/html5/thumbnails/38.jpg)
38
DiscussionComponentoperation(..)add(component)remove(component) getChild(k)
Compositeoperation(..)add(component)remove(component) getChild(k)
Leafoperation(..)
* components
• Forcing some operations on Leaf• Circularity• getChild does not seem very useful
children () : List<Component>(alternatively, return an iterator)
![Page 39: Design Pattern 2 [FF 6 – 11]. Remember Starbuzz Coffee? 2 Coffee instruction 1.Boil water 2.Brew coffee in boiling water 3.Pour the mix in cup 4.Add sugar](https://reader035.vdocument.in/reader035/viewer/2022062713/56649cf55503460f949c4c20/html5/thumbnails/39.jpg)
39
Implementation
<<interface>>MenuComponentoperation(..)
Menuadd(component)remove(component)
MenuItemnamedescprice
* components
class Menu { components = new LinkedList<...>()
add(c) { components.add(c) } remove(c) { components.remove(c) }
}
![Page 40: Design Pattern 2 [FF 6 – 11]. Remember Starbuzz Coffee? 2 Coffee instruction 1.Boil water 2.Brew coffee in boiling water 3.Pour the mix in cup 4.Add sugar](https://reader035.vdocument.in/reader035/viewer/2022062713/56649cf55503460f949c4c20/html5/thumbnails/40.jpg)
40
Operation : counting menu items
<<interface>>MenuComponentcountMenuItems()
Menuadd(component)remove(component)
MenuItemnamedescprice
* components class Menu { components …
countMenuItems() { n = 0 for (MenuComponent m : components) n += m.countMenuItems()) return n }}
class MenuItem { countMenuItems() { return 1 }}
![Page 41: Design Pattern 2 [FF 6 – 11]. Remember Starbuzz Coffee? 2 Coffee instruction 1.Boil water 2.Brew coffee in boiling water 3.Pour the mix in cup 4.Add sugar](https://reader035.vdocument.in/reader035/viewer/2022062713/56649cf55503460f949c4c20/html5/thumbnails/41.jpg)
41
Operation : getting the cheapest menu item
<<interface>>MenuComponentcountMenuItems()getCheapest()
Menuadd(component)remove(component)
MenuItemnamedescprice
* components class Menu { components …
getCheapest() { p = MAXINT c = null for (MenuComponent m : components) { d = m.getCheapest() if (d != null && d.price < p) { c = d ; p = d.price } } return c }}
class MenuItem { getCheapest() { return this }}