CMPT 300 Design Patterns
May 2008

Lab 3  - The Decorator Pattern



<< lab3.zip >>

The Decorator pattern is used to dynamically assign responsibilities at runtime. They provide a flexible alternative to subclassing (inheritance ... which is done at compile time)  for extending functionality.


An example

Ice Cream

Suppose we have three flavors of ice cream: Chocolate, Strawberry, and Vanilla. Also assume we may also want to add a cherry, hot fudge, or whipped cream to the ice cream. (These can all be added, or just a cherry, or whipped cream and hot fudge, etc.)

We have various techniques for solving this (inheritance, etc.), but the Decorator pattern allows us to dynamically change an Ice Cream object at run time.


In UML,

Decorator


The Java classes:

- IceCream.java

- Chocolate.java

- Strawberry.java

- IceCreamDecorator.java

- Cherry.java

- Holstein.java


The Lab: Part I

I. Add another flavor - Vanilla - which costs 1.25

II. Add two separate decorators for (1) whipped cream, and (2) hot fudge. Whipped cream costs an extra .25, hot fudge is .60. Modify the test program (Holstein.java) so that you create various combinations of different flavored ice cream cones with cherry, whipped cream, and hot fudge.

III. Using pencil-and-paper, sketch the UML class diagrams for all ice cream classes illustrating how they use the Decorator.



Another Example

The java.io package has widely practiced the Decorator pattern. As a very small example:

java.io Decorators

An example program:

          - IOExample.java - a program illustrating how the java.io package uses decorators.

        A more interesting example where we decorate

- IO.java

- CaesarShiftInputStream.java

This program uses file.txt

Notice how we wrap (decorate) a FilterInputStream with CaesarShiftInputStream.

The Lab: Part II

One way to send a flame is to write a message using ENTIRELY UPPER CASE LETTERS.

Write a decorator called FlameInputStream that takes a file and turns all letters {a..z} into their upper-case equivalents.  You will use a similar technique to CaesarShiftInputStream.java, except that the read() method will turn all letters into uppercase. You may find some methods in the Character class useful.


This will require modifying IO.java as well.


What to Submit to Receive Credit for This Lab:

When you have completed this lab, please show me:

1. The UML drawing from Part I

2. Classes for the vanilla ice cream flavor as well as the whipped cream and hot fudge decorators. In addition, demonstrate your new decorators work properly by demonstrating your modified Holstein program.

3. FlameInputStream class.