Model subclass: #DispensingHolder instanceVariableNames: 'items ' classVariableNames: '' poolDictionaries: '' category: 'Vending'! !DispensingHolder methodsFor: 'initialize-release'! initialize items := OrderedCollection new! ! !DispensingHolder methodsFor: 'connections'! connectToItem: aItem items add: aItem.! disconnectWithItem: aItem items remove: aItem ifAbsent: []! items "Return the current value of items." ^items! ! !DispensingHolder methodsFor: 'dispensing'! activateDispenser ^self! dispense: itemToDispense "Dispense the item. Return true if successful, otherwise false." self isEmpty ifTrue: [^false]. (self itemIsDispensable: itemToDispense) ifFalse: [^false]. self printItem: itemToDispense . Transcript cr; show: 'Items left in this Holder:'; space; show: (items size) printString ; cr. self activateDispenser. self disconnectWithItem: itemToDispense. ^true! ! !DispensingHolder methodsFor: 'testing'! isEmpty ^items isEmpty! itemIsDispensable: itemToDispense "Check if the first item and the item to dispense are the same object. Be sure to use == rather than =." ^items first == itemToDispense! ! !DispensingHolder methodsFor: 'simulating'! printItem: itemToDispense Transcript cr. Transcript show: 'Releasing ' , itemToDispense printString.! ! !DispensingHolder methodsFor: 'view access'! dispensableHolderSize ^self isEmpty ifTrue: [0] ifFalse: [items size]! dispensableItemName ^self isEmpty ifTrue: ['Empty'] ifFalse: [items first name]! dispensableItemPrice ^self isEmpty ifTrue: [0] ifFalse: [items first price]! vendTheDispensableItem self isEmpty ifTrue: [^false]. items first vend ifFalse: [^false]. self changed: #dispensableItemName. self changed: #dispensableItemPrice. self changed: #dispensableHolderSize! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! DispensingHolder class instanceVariableNames: ''! !DispensingHolder class methodsFor: 'instance creation'! new ^super new initialize! ! Model subclass: #CashDevice instanceVariableNames: 'amountCollected ' classVariableNames: '' poolDictionaries: '' category: 'Vending'! !CashDevice methodsFor: 'initialize-release'! initialize amountCollected := 0.! ! !CashDevice methodsFor: 'accessing'! amountCollected "Return the current value of amount collected " ^amountCollected! amountCollected: newValue "Set the value of amount collected. Notify my dependents that I've changed" amountCollected := newValue. self changed: #amountCollected! ! !CashDevice methodsFor: 'cash collecting'! gotEnough: amountToCollect "Return true if the amount collected is greater than or equal to the amount to be collected." ^ amountCollected >= amountToCollect! makeChangeFor: aPrice self amountCollected: amountCollected - aPrice! return "Reset the cash collected. Return false to indicate cash not collected" self amountCollected: 0. ^false! ! !CashDevice methodsFor: 'simulating'! addCash "Increase my amount collected by some default increment." self amountCollected: (amountCollected + self cashIncrement)! cashIncrement ^0.25! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! CashDevice class instanceVariableNames: ''! !CashDevice class methodsFor: 'instance creation'! new ^super new initialize! ! Model subclass: #Item instanceVariableNames: 'name price dispensingHolder cashDevice ' classVariableNames: '' poolDictionaries: '' category: 'Vending'! !Item methodsFor: 'initialize-release'! initialize name := String new. price := 0.0! ! !Item methodsFor: 'accessing'! name "Return my name" ^name! name: aName "Set the value of name. Notify my dependents that I've changed" name := aName. self changed: #name! price "Return my price " ^price! price: aPrice "Set the value of price. Notify my dependents that I've changed" price := aPrice. self changed: #price! ! !Item methodsFor: 'connections'! cashDevice "Return the current value of cash device" ^cashDevice! connectToCashDevice: aCashDevice cashDevice := aCashDevice! connectToDispensingHolder: aDispensingHolder dispensingHolder := aDispensingHolder! dispensingHolder ^dispensingHolder! ! !Item methodsFor: 'printing'! printOn: aStream aStream nextPutAll: 'item: '; space; space. aStream nextPutAll: name printString; space; space; space. aStream nextPutAll: ' price: '; space; space. aStream nextPutAll: price printString! ! !Item methodsFor: 'vending'! vend | success | self isVendable ifFalse: [Screen default ringBell. ^false]. success := dispensingHolder dispense: self. success ifFalse: [^false]. cashDevice makeChangeFor: price. ^true! ! !Item methodsFor: 'testing'! isVendable ^cashDevice gotEnough: price! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! Item class instanceVariableNames: ''! !Item class methodsFor: 'instance creation'! new ^super new initialize! ! !Item class methodsFor: 'vending demos'! connectItem: aName price: aPrice to: aDispensingHolder and: aCashDevice | anItem | anItem := self new name: aName; price: aPrice. anItem connectToDispensingHolder: aDispensingHolder. anItem connectToCashDevice: aCashDevice. aDispensingHolder connectToItem: anItem! simpleDemo | item1 item2 item3 items aDispensingHolder aCashDevice | item1 := (Item new) name: 'Coca-Cola'; price: 0. item2 := (Item new) name: 'Pepsi'; price: 0. item3 := (Item new) name: 'Jolt'; price: 0. items := OrderedCollection with: item1 with: item2 with: item3. aDispensingHolder := DispensingHolder new. aCashDevice := CashDevice new. items do: [:anItem | aDispensingHolder connectToItem: anItem. anItem connectToDispensingHolder: aDispensingHolder. anItem connectToCashDevice: aCashDevice]. ^ItemViewContainer new openOn: aDispensingHolder! vendingMachineDemo | dispensingHolders aDispensingHolder aCashDevice | dispensingHolders := OrderedCollection new. aCashDevice := CashDevice new. aDispensingHolder := DispensingHolder new. dispensingHolders add: aDispensingHolder. 4 timesRepeat: [self connectItem: 'Coca-Cola' price: 0.75 to: aDispensingHolder and: aCashDevice]. aDispensingHolder := DispensingHolder new. dispensingHolders add: aDispensingHolder. 6 timesRepeat: [self connectItem: 'Pepsi' price: 0.75 to: aDispensingHolder and: aCashDevice]. aDispensingHolder := DispensingHolder new. dispensingHolders add: aDispensingHolder. 3 timesRepeat: [self connectItem: 'Jolt' price: 0.75 to: aDispensingHolder and: aCashDevice]. ItemViewContainer vendingMachineDemoFor: dispensingHolders and: aCashDevice! !