Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Luca Vigan
Dipartimento di Informatica Universit di Verona
Decorator
1 / 20
Decorating Classes
Youll learn how to decorate your classes at runtime using a form of object composition. Why? Once you know the techniques of decorating, youll be able to give your (or someone elses) objects new responsibilities without making any code changes to the underlying classes.
Decorator
2 / 20
Decorator
3 / 20
Decorator
4 / 20
Think!
Its pretty obvious that Starbuzz has created a maintenance nightmare for themselves.
What happens when the price of milk goes up? What do they do when they add a new caramel topping? Thinking beyond the maintenance problem, which of the design principles that weve covered so far are they violating?
Decorator
5 / 20
A possible solution?
Why do we need all these classes? Cant we just use instance variables and inheritance in the superclass to keep track of the condiments?
Decorator
6 / 20
A possible solution?
Lets add in the subclasses, one for each beverage on the menu:
Decorator
7 / 20
Brain Teaser
Decorator
8 / 20
Problems?
What requirements or other factors might change that will impact this design?
Price changes for condiments will force us to alter existing code. New condiments will force us to add new methods and alter the cost method in the superclass. We may have new beverages. For some of these beverages (iced tea?), the condiments may not be appropriate, yet the Tea subclass will still inherit methods like hasWhip(). (remember Strategy?) What if a customer wants a double mocha?
Decorator
9 / 20
Design Principle Classes should be open for extension, but closed for modication. Feel free to extend classes with any new behavior you like. If your needs or requirements change (and we know they will), just go ahead and make your own extensions. But we spent a lot of time getting this code correct and bug free, so we cant let you alter the existing code. It must remain closed to modication.
Decorator
10 / 20
Well start with a beverage and decorate it with the condiments at runtime. For example if the customer wants a Dark Roast with Mocha and Whip, then well:
1) 2) 3) 4) Take a DarkRoast object Decorate it with a Mocha object Decorate it with a Whip object Call the cost() method and rely on delegation to add on the condiment costs
Decorator
11 / 20
Remember hat DarkRoast inherits from Beverage and has a cost() method that computes the cost of the drink.
Decorator
12 / 20
The Mocha object is a decorator: its type mirrors (i.e. it is the same type) the object it is decorating, in this case, a Beverage. So, Mocha has a cost() method too, and through polymorphism we can treat any Beverage wrapped in Mocha as a Beverage, too (because Mocha is a subtype of Beverage).
Decorator
13 / 20
Whip is a decorator, so it also mirrors DarkRoasts type and includes a cost() method. So, a DarkRoast() wrapped in Mocha and Whip is still a Beverage and we can do anything with it we can do with a DarkRoast, including call its cost() method.
Decorator
14 / 20
Decorator
15 / 20
First, we call cost() on the outmost decorator, Whip. Whip calls cost() on Mocha. Mocha calls cost() on DarkRoast. DarkRoast returns its cost: 99 cents. Mocha adds its cost, 20 cents, to the result from DarkRoast, and returns the new total: $ 1.19. Whip adds its total, 10 cents, to the result from Mocha, and returns the nal result: $ 1.29.
Luca Vigan (Universit di Verona) Decorator Lab. Ing. del SW, 06.05.2011 16 / 20
Decorator
18 / 20
Decorator
19 / 20
OO Principles
Encapsulate what varies Favor composition over inheritance Program to interfaces, not implementations Strive for loosely coupled designs between objects that interact Classes should be open for extension but closed for modication
Its time to turn this design into some real Starbuzz code!
Decorator
20 / 20