Presentation is loading. Please wait.

Presentation is loading. Please wait.

7. Decorator SE2811 Software Component Design

Similar presentations


Presentation on theme: "7. Decorator SE2811 Software Component Design"— Presentation transcript:

1 7. Decorator SE2811 Software Component Design
Dr. Rob Hasker (based on slides by Dr. Mark Hornick) 7. Decorator

2 The Decorator Pattern

3 Example: Ice Cream Store
Confection: “a dish or delicacy made with sweet ingredients” IceCreamConfection: either an interface or abstract Show methods once! Description: maybe an attribute, maybe computed Why might costInCents return an int? Don’t need to show methods in subclasses – LSP says they are there automatically, so they just add clutter!

4 Implementation Doubles would only help a bit…
public class Money { private static float BIG_VALUE = 1e8F; public static void main(String[] args) { float num = BIG_VALUE; for(int i = 0; i < 1000; ++i) num += 1.0; System.out.println(BIG_VALUE + " : " + num); num = 0.0F; num += BIG_VALUE; System.out.println(" " + BIG_VALUE + ": " + num); } // output: 1.0E : 1.0E8 E8: E8 Implementation public abstract class IceCream { String description; public String getDescription() { return description; } public abstract int costInCents(); public class Cone extends IceCream { public Cone() { description = “Cone”; } public int costInCents() { return 124; + is not commutative over floats and doubles – this is not good for monetary amounts! (You’d have more money if you deposited small amounts into your account before large amounts!) Doubles would only help a bit… Why use cents and not a double?

5 Implementation Why use cents and not a double?
public abstract class IceCreamConfection { public abstract String description(); public abstract int costInCents(); } public class Cone extends IceCreamConfection { public String description() { return “Cone”; } public int costInCents() { return 124; Why use cents and not a double?

6 Example: Ice Cream Store
But how to track sprinkles? fudge?

7 Extending functionality
CS-1020 4/3/2019 Extending functionality Store sells many topics: fudge, M&Ms, peanuts Sorry, you’ll have to visit Skylight after class Each topping: additional cost These are college students! How should we design the system? College students will park a meal on an ice cream cone… Dr. Mark L. Hornick

8 Decorator Pattern: Goals
Goal: attach additional functionality to an existing class at runtime Goal: avoid extra subclassing Are there cases where you CANNOT subclass? Yes: if base class declared final Goal: avoid modifying existing class … especially if no access to source or the base class used elsewhere

9 Alternative 1: Create a new class for each combination.
Ice Cream Toppings Cone M&M Dish Fudge WaffleCone Peanuts Caramel What can go wrong? Results in class explosion! What happens when a new topping is added? What happens when the cost of a topping (e.g. fudge) changes? Maintenance nightmare!

10 Alternative 2: Flags for the toppings
IceCream public class IceCream { public double costInCents() { int toppingCost = 0; if (hasFudge()) toppingCost += FUDGE_COST; if (hasCaramel()) toppingCost += CARAMEL_COST; return toppingCost; } -description: String -hasFudge: boolean -hasMnM: boolean +getDescription() +cost() +hasFudge() +hasCaramel() ------ Challenge: doesn’t work well with more complex behavior

11 Alternative 2, continued
public class Cone { public double costInCents() { return super.cost(); } What is this method calculating and returning?

12 So what’s the problem? We want to allow existing classes to be easily adapted to incorporate new behavior without modifying existing code. We want a design that is flexible enough to take on new functionality to meet changing requirements. Solution: Decorator Pattern

13 Warning: make sure the base class (Component) is an interface, otherwise the decorator will have an additional data value and you lose identity. If there’s something in common between ConcreteComponentA and ConcreteComponentB, create a subclass of Component that captures that commonality. Note: *really* want the base class (Component) to be an interface, otherwise you will have two copies of any Component attributes.

14 DecoratedConfection: abstract since need common wrappedItem for all decorations
Decoration: gives a new item that has all of the same properties, interface as the original An IceCreamWithFudge also defines cost(), description()

15 abstract class DecoratedConfection implements IceCreamConfection {
protected IceCreamConfection wrappedItem; public DecoratedConfection(IceCreamConfection icc) { wrappedItem = icc; } public double costInCents() { return wrappedItem.cost() + 25; } // all decorations +25 cents } public class IceCreamWithFudge extends DecoratedConfection { public IceCreamWithFudge(IceCreamConfection icc) { super(icc); } public String description() { return wrappedItem.description() + “ with fudge”; } The full example is at

16 Using the Decorator Pattern
Start by creating an IceCreamConfection object: IceCreamConfection toServe = new Cone(); Decorate it with the Fudge topping. Create a IceCreamWithFudge object and wrap it around the item to serve: toServe = new IceCreamWithFudge(toServe); Decorate it with the Nuts topping. Create a IceCreamWithNuts object and wrap it around the item to serve: toServe = new IceCreamWithNuts(toServe); Call the cost method and rely on delegation to add the cost of all toppings: System.out.println(toServe.cost());

17 What’s going on here? Open-closed principle: Can extend at will
Classes should be open for extension, but closed to modification Can extend at will No final classes!? Supports new applications of existing code Don’t alter the existing code! It may be used elsewhere! At the least it means new unit tests

18 Evaluation What’s good about the decorator? What’s bad?
CS-1020 4/3/2019 Evaluation What’s good about the decorator? What’s bad? Impact on coupling? Impact on cohesion? Good: can provide new functionality/responsibilities on old classes; Bad: it’s not clear! You do get some extra classes, but it’s far fewer extra classes than the combinatorial explosion from handling all combinations…. Coupling: no change to coupling between confections and rest of system; cohesion of new classes very strong (all functionality for the new operations in one place); cohesion of existing classes unchanged (which is good). Dr. Mark L. Hornick

19 Summary Decorators: same super-type as objects being decorated
One or more decorators can be used to wrap an object Can pass decorated object anywhere original can be passed Decorated: adds behavior before or after delegating to the decorated object Can decorate objects at run time … with multiple decorators Supports open-closed principle: open to extension, closed to modification

20 java.io: many classes for I/O
OutputStream, FileOutputStream, PipedOutputStream, DataOutputStream, ObjectOutputStream, PrintStream, PrintWriter, … Associations between these not clear from Java API documentation

21 But note: simply applying Decorator

22 Decorator pattern applied to input streams:
Create custom stream decorators by extending FilterOutputStream and FilterInputStream

23 Demonstration


Download ppt "7. Decorator SE2811 Software Component Design"

Similar presentations


Ads by Google