SlideShare ist ein Scribd-Unternehmen logo
1 von 40
Decorator Pattern

Applied to I/O stream classes
Design Principle
• Classes should be open for extension, but
  closed for modification
  – Apply the principle to the areas that are most
    likely to change
Decorator Pattern
• Attaches additional responsibilities to an object
  dynamically. Decorator provides a flexible
  alternative to subclassing for extending
  functionality.
• Example: StarBuzz Coffee
   – Several blends
      • HouseBlend, DarkRoast, Decaf, Espresso
   – Condiments
      • Steamed milk, soy, mocha, whipped milk
   – Extra charge for each
   – How do we charge all combinations?
      • First attempt: inheritance
See Decorator0
<<abstract>>            The description instance
                                                             variable is set in each
                                      Beverage               subclass and holds a
                                                             description of the
                                  description                beverage, like “Java Dark
                                                             Roast”
                                  getDescription()

  Cost() method is                cost()
                                                             getDescription() method
  abstract. Subclasses                                       returns the description
  need to implement
  their own
  implementation




HouseBlend                DarkRoast                  Decaf              Espresso
cost()                   cost()                 cost()                cost()


         Each subclass implements cost() to return the cost of the beverage
Problem with first attempt:
• How do we add the condiments?
  – Apply subclass and inheritance
    • Add subclasses and inheritance for condiments
    • But there can be combinations of condiments
• Class explosion when all combinations are
  considered
  – There must be a better way
  – Can we treat condiments as instance
    variables and apply inheritance?
<<abstract>>
                                  Beverage
                         description: String
                         milk: boolean         New boolean values for
                                               each condiment
                         soy: boolean
                         mocha: boolean
                         whip: boolean
                         getDescription()      We implement cost() in
Beverage’s cost()                              Beverage (instead of
                         cost()
calculates the cost of                         keeping it abstract), so that it
condiments.                                    can calculate the costs
                                               associated with the
The subclasses           hasMilk()
                                               condiments for a particular
calculate the cost of    setMilk()             beverage instance.
the beverage and add                           Subclasses will still override
the cost of condiments   hasSoy()
                                               cost(), but they also invoke
                         setSoy()              the super version to
                                               calculate the total cost() of
                         hasMocha()
                                               the basic beverage plus the
                         setMocha()            costs of the added
                                               condiments.
                         hasWhip()
                         setWhip()
Decorator1
• Run example Decorator1
Decorator1: Any problem?
• Our goal is to simplify maintenance.
  – Prices can change – code change
  – New condiments – add new methods and
    alter cost method in superclass
  – New beverages e.g. tea
  – Double mocha?
• Code changes in the superclass when the
  above happens or in using combinations
Design Principle
• Classes should be open for extension, but
  closed for modification
  – Apply the principle to the areas that are most
    likely to change
• We want our designs that are resilient to
  change and flexible enough to take on
  new functionality to meet changing
  requirements
How?
• We want techniques to allow code to be
  extended without direct modification
Start with a beverage and decorate
   it with condiments at run time
• Example:
  – 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 the condiment costs
cost()
   DarkRoast




cost()      cost()
            DarkRoast
     Mocha


                                      cost()         cost()         cost()

                               0.10            .20            .99   DarkRoast
                        1.29
                                                        Mocha
                                         Whip
Decorator Pattern
• The Decorator Pattern attaches additional
  responsibilities to an object dynamically.
  Decorators provide a flexible alternative to
  subclassing for extending functionality
• See class diagram on the next slide
Each component can be used on
                                 Component
                                                     its own, or wrapped by a decorator
                                methodA()
                                                                 component
                                methodB()                               Each decorator
                                                                        HAS_A (wraps) a
                                                                        component i.e. the
                                                                        decorator has an
                                                                        instance variable
                                                                        that holds a
   ConcreteComponent                              Decorator
                                                                        reference to a
                                              methodA()                 component
  methodA()
  methodB()                                   methodB()



The ConcreteDecorator         ConcreteDecoratorA                  ConcreteDecoratorB
has an instance variable
                              Component wrappedObj                Component wrappedObj
for the thing it decorates
(the component the            methodA()                           Object newState
Decorator wraps)
                              methodB()                           methodA()
Decorator can add new         newBehavior()                       methodB()
methods
                             Can extend state of the component    newBehavior()
Beverage acts as
abstract component                                           component
class




   4 concrete
   components, 1 per
   coffee type




                       The condiment decorators. They need to implement not
                       only cost() but also getDescription()
Discussion
• It appears that the condimentDecorator is
  a subclass of Beverage
  – Really we are subclassing to get the correct
    type, not to inherit its behavior
  – When we compose a decorator with a
    component, we are adding new behavior
  – Inheritance: the behavior is determined
    statically at compile time
  – Composition: we can mix and match
    decorators any way we like at runtime.
More: Inheritance vs composition
Inheritance           Composition
• Need to change      • Can implement new
  existing code any     decorators at any
  time we want new      time to add new
  behavior              behavior
One more question:
• We started with Beverage as an abstract
  class in Java. Can it be an interface in
  Java?
• Discussion: yes or no? Why?
Code Study:Decorator project -
         Beverage
public abstract class Beverage {
         String description = "Unknown Beverage";

        public String getDescription() {   // already implemented
                return description;
        }

        public abstract double cost();     // Need to implement cost()
}
Condiments (Decorator) class
                                                   We need to be
                                                   interchangeable with a
                                                   Beverage, so extend the
                                                   Beverage class – not to get its
                                                   behavior but its type

public abstract class CondimentDecorator extends Beverage {

        public abstract String getDescription();
}

                        Here we require all the condiment decorators
                        reimplement the getDescription() method.
                        Explanations coming
Coding beverages
public class HouseBlend extends Beverage {
                                                        Note the description
        public HouseBlend() {                           variable is inherited
                description = "House Blend Coffee";     from Beverage. To
        }                                               take care of
                                                        description, put this
        public double cost() {                          in the constructor for
                                                        the class
                return .89;
        }
}              Compute the cost of a HouseBlend. Need
               not worry about condiments
Coding condiments
            Mocha is decorator, so extend CondimentDecorator, which extends Beverage

public class Mocha extends CondimentDecorator {             Instantiate Mocha with
  Beverage beverage;                                            a reference to a
                                                                Beverage using
  public Mocha(Beverage beverage) {                         1. An instance variable
     this.beverage = beverage;                                 to hold the
  }                                                            beverage we are
                                                               wrapping
  public String getDescription() {                         2. A way to set this
    return beverage.getDescription() + ", Mocha";             instance to the
  }                                                           object we are
                                  We want the description to wrapping – we pass
                                  include the beverage –      the beverage we
  public double cost() {          say Houseblend – and the are wrapping to the
    return .20 + beverage.cost(); condiments
  }                                                           decorator’s
     Cost of condiment + cost of                              constructor
}    beverage
public class StarbuzzCoffee {

    public static void main(String args[]) {
      Beverage beverage = new Espresso(); // espresso order, no condiments
      System.out.println(beverage.getDescription()
                     + " $" + beverage.cost());

         Beverage beverage2 = new DarkRoast();           // get a DarkRoast
         beverage2 = new Mocha(beverage2);               // wrap it with Mocha
         beverage2 = new Mocha(beverage2);               // warp it with Mocha
         beverage2 = new Whip(beverage2);                // Wrap it with a Whip
         System.out.println(beverage2.getDescription()
                     + " $" + beverage2.cost());

         Beverage beverage3 = new HouseBlend();          // get a Houseblend
         beverage3 = new Soy(beverage3);                 // wrap with Soy
         beverage3 = new Mocha(beverage3);               // wrap with Mocha
         beverage3 = new Whip(beverage3);                // wrap with Whip
         System.out.println(beverage3.getDescription()
                     + " $" + beverage3.cost());
     }
}
Executing StarBuzzCoffee
Summary
1. CondimentDecorator extends Beverage
   class
  – Purpose: the decorators have the same type
    as the objects they are decorating
  – Inheritance is used to achieve type matching
  – Inheritance is NOT used to get behavior
1. Where does the behavior come in?
  – We acquire behavior not by inheriting from a
    superclass, but by composing objects
    together
Summary
3.  We subclass the abstract class Beverage to have the
   correct type not to inherit its behavior
4. The behavior comes in through the composition of
   decorators with the base components as well as other
   decorators
5. Because we are using object composition, we get a
   more flexibility about how to mix and match condiments
   and beverages.
6. Inheritance determines the behavior at compile time.
   With composition, we can mix and match decorators any
   way at will at runtime.
Summary
7. We started with Beverage as an abstract
   class in Java. Could it be an interface in
   Java?
Since all we need to inherit is the type of
   component, we could use an interface in
   Java.
Decorator

Decorating the java.io classes
Abstract
                                    InputStream              component



                                                                 FilterInputStream is an
FileInputStream
                                                                 ‘abstract’ decorator
      StringBufferInputStream                         FilterInputStream


                ByteArrayInputStream

 These InputStreams
 act as concrete                                                  PushBackInputStream
 components, to be
 wrapped with
 decorators                                                                   Concrete
                                                        DataInputStream       decorators

    LineNumberInputStream        BufferedInputStream
    Ablity to count line
                                 •Buffers input for
    numbers as it reads data
                                 performance
                                 •Methods readLine(),
                                 mark(), reset()
Writing your own Java I/O decorator

• We have learned the decorator pattern
• And I/O class diagram
• Write a decorator that converts all
  uppercase characters to lowercase
  characters in the input stream
Extend the FilterInputStream, the
                                      abstract decorator for all
import java.io.*;                     inputStream

public class LowerCaseInputStream extends FilterInputStream {

         public LowerCaseInputStream(InputStream in) {
                  super(in);
                                                Implement 2 read() methods, taking a
         }                                      byte (or an array of bytes) and convert
                                                      each byte to lowercase if it is an
         public int read() throws IOException {       uppercase character
                   int c = super.read();
                   return (c == -1 ? c : Character.toLowerCase((char)c));
         }

         public int read(byte[] b, int offset, int len) throws IOException {
                   int result = super.read(b, offset, len);
                   for (int i = offset; i < offset+result; i++) {
                               b[i] = (byte)Character.toLowerCase((char)b[i]);
                   }
                   return result;
         }
}
import java.io.*;

public class InputTest {
  public static void main(String[] args) throws IOException {
     int c;
                                                              Set up fileInputStream and
                                                              decorate it, first with
        try {                                                 BufferedInputSteam and then
                InputStream in =                              LowercaseInputStream filter.
                   new LowerCaseInputStream(
                     new BufferedInputStream(
                         new FileInputStream("test.txt")));

                while((c = in.read()) >= 0) {
                System.out.print((char)c);
                }

            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
Executing project IO
• Test.txt contains “I now know the
  DECORATOR PATTERN.”

Weitere ähnliche Inhalte

Was ist angesagt?

Spring introduction
Spring introductionSpring introduction
Spring introductionManav Prasad
 
Android styles and themes
Android styles and themesAndroid styles and themes
Android styles and themesSourabh Sahu
 
9월 웨비나 - AWS에서의 네트워크 보안 (이경수 솔루션즈 아키텍트)
9월 웨비나 - AWS에서의 네트워크 보안 (이경수 솔루션즈 아키텍트)9월 웨비나 - AWS에서의 네트워크 보안 (이경수 솔루션즈 아키텍트)
9월 웨비나 - AWS에서의 네트워크 보안 (이경수 솔루션즈 아키텍트)Amazon Web Services Korea
 
Spring core module
Spring core moduleSpring core module
Spring core moduleRaj Tomar
 
Amazon DocumentDB vs MongoDB 의 내부 아키텍쳐 와 장단점 비교
Amazon DocumentDB vs MongoDB 의 내부 아키텍쳐 와 장단점 비교Amazon DocumentDB vs MongoDB 의 내부 아키텍쳐 와 장단점 비교
Amazon DocumentDB vs MongoDB 의 내부 아키텍쳐 와 장단점 비교Amazon Web Services Korea
 
The Singleton Pattern Presentation
The Singleton Pattern PresentationThe Singleton Pattern Presentation
The Singleton Pattern PresentationJAINIK PATEL
 
더욱 진화하는 AWS 네트워크 보안 - 신은수 AWS 시큐리티 스페셜리스트 솔루션즈 아키텍트 :: AWS Summit Seoul 2021
더욱 진화하는 AWS 네트워크 보안 - 신은수 AWS 시큐리티 스페셜리스트 솔루션즈 아키텍트 :: AWS Summit Seoul 2021더욱 진화하는 AWS 네트워크 보안 - 신은수 AWS 시큐리티 스페셜리스트 솔루션즈 아키텍트 :: AWS Summit Seoul 2021
더욱 진화하는 AWS 네트워크 보안 - 신은수 AWS 시큐리티 스페셜리스트 솔루션즈 아키텍트 :: AWS Summit Seoul 2021Amazon Web Services Korea
 
진화하는 CloudFront 의 이해와 글로벌 서비스 활용 - 안수일 시니어 솔루션즈 아키텍트, GS NEOTEK :: AWS Summit...
진화하는 CloudFront 의 이해와 글로벌 서비스 활용 - 안수일 시니어 솔루션즈 아키텍트, GS NEOTEK :: AWS Summit...진화하는 CloudFront 의 이해와 글로벌 서비스 활용 - 안수일 시니어 솔루션즈 아키텍트, GS NEOTEK :: AWS Summit...
진화하는 CloudFront 의 이해와 글로벌 서비스 활용 - 안수일 시니어 솔루션즈 아키텍트, GS NEOTEK :: AWS Summit...Amazon Web Services Korea
 
Scalable JavaScript Application Architecture
Scalable JavaScript Application ArchitectureScalable JavaScript Application Architecture
Scalable JavaScript Application ArchitectureNicholas Zakas
 
Introduction to mvc architecture
Introduction to mvc architectureIntroduction to mvc architecture
Introduction to mvc architectureravindraquicsolv
 
File Handling in Java Oop presentation
File Handling in Java Oop presentationFile Handling in Java Oop presentation
File Handling in Java Oop presentationAzeemaj101
 
AWS와 함께 하는 Unity 게임 배포 및 운영 전략 - AWS Summit Seoul 2017
AWS와 함께 하는 Unity 게임 배포 및 운영 전략 - AWS Summit Seoul 2017AWS와 함께 하는 Unity 게임 배포 및 운영 전략 - AWS Summit Seoul 2017
AWS와 함께 하는 Unity 게임 배포 및 운영 전략 - AWS Summit Seoul 2017Amazon Web Services Korea
 

Was ist angesagt? (20)

Spring introduction
Spring introductionSpring introduction
Spring introduction
 
AWS Lambda
AWS LambdaAWS Lambda
AWS Lambda
 
Factory Design Pattern
Factory Design PatternFactory Design Pattern
Factory Design Pattern
 
Android styles and themes
Android styles and themesAndroid styles and themes
Android styles and themes
 
9월 웨비나 - AWS에서의 네트워크 보안 (이경수 솔루션즈 아키텍트)
9월 웨비나 - AWS에서의 네트워크 보안 (이경수 솔루션즈 아키텍트)9월 웨비나 - AWS에서의 네트워크 보안 (이경수 솔루션즈 아키텍트)
9월 웨비나 - AWS에서의 네트워크 보안 (이경수 솔루션즈 아키텍트)
 
Spring core module
Spring core moduleSpring core module
Spring core module
 
Amazon DocumentDB vs MongoDB 의 내부 아키텍쳐 와 장단점 비교
Amazon DocumentDB vs MongoDB 의 내부 아키텍쳐 와 장단점 비교Amazon DocumentDB vs MongoDB 의 내부 아키텍쳐 와 장단점 비교
Amazon DocumentDB vs MongoDB 의 내부 아키텍쳐 와 장단점 비교
 
Adapter pattern
Adapter patternAdapter pattern
Adapter pattern
 
The Singleton Pattern Presentation
The Singleton Pattern PresentationThe Singleton Pattern Presentation
The Singleton Pattern Presentation
 
더욱 진화하는 AWS 네트워크 보안 - 신은수 AWS 시큐리티 스페셜리스트 솔루션즈 아키텍트 :: AWS Summit Seoul 2021
더욱 진화하는 AWS 네트워크 보안 - 신은수 AWS 시큐리티 스페셜리스트 솔루션즈 아키텍트 :: AWS Summit Seoul 2021더욱 진화하는 AWS 네트워크 보안 - 신은수 AWS 시큐리티 스페셜리스트 솔루션즈 아키텍트 :: AWS Summit Seoul 2021
더욱 진화하는 AWS 네트워크 보안 - 신은수 AWS 시큐리티 스페셜리스트 솔루션즈 아키텍트 :: AWS Summit Seoul 2021
 
For Beginers - ADO.Net
For Beginers - ADO.NetFor Beginers - ADO.Net
For Beginers - ADO.Net
 
진화하는 CloudFront 의 이해와 글로벌 서비스 활용 - 안수일 시니어 솔루션즈 아키텍트, GS NEOTEK :: AWS Summit...
진화하는 CloudFront 의 이해와 글로벌 서비스 활용 - 안수일 시니어 솔루션즈 아키텍트, GS NEOTEK :: AWS Summit...진화하는 CloudFront 의 이해와 글로벌 서비스 활용 - 안수일 시니어 솔루션즈 아키텍트, GS NEOTEK :: AWS Summit...
진화하는 CloudFront 의 이해와 글로벌 서비스 활용 - 안수일 시니어 솔루션즈 아키텍트, GS NEOTEK :: AWS Summit...
 
Ooad
OoadOoad
Ooad
 
Scalable JavaScript Application Architecture
Scalable JavaScript Application ArchitectureScalable JavaScript Application Architecture
Scalable JavaScript Application Architecture
 
Event handling
Event handlingEvent handling
Event handling
 
Introduction to mvc architecture
Introduction to mvc architectureIntroduction to mvc architecture
Introduction to mvc architecture
 
File Handling in Java Oop presentation
File Handling in Java Oop presentationFile Handling in Java Oop presentation
File Handling in Java Oop presentation
 
AWS와 함께 하는 Unity 게임 배포 및 운영 전략 - AWS Summit Seoul 2017
AWS와 함께 하는 Unity 게임 배포 및 운영 전략 - AWS Summit Seoul 2017AWS와 함께 하는 Unity 게임 배포 및 운영 전략 - AWS Summit Seoul 2017
AWS와 함께 하는 Unity 게임 배포 및 운영 전략 - AWS Summit Seoul 2017
 
The API Economy
The API EconomyThe API Economy
The API Economy
 
Amazon EC2 Container Service
Amazon EC2 Container ServiceAmazon EC2 Container Service
Amazon EC2 Container Service
 

Andere mochten auch

Phani Kumar - Decorator Pattern
Phani Kumar - Decorator PatternPhani Kumar - Decorator Pattern
Phani Kumar - Decorator Patternmelbournepatterns
 
Decorator design pattern (A Gift Wrapper)
Decorator design pattern (A Gift Wrapper)Decorator design pattern (A Gift Wrapper)
Decorator design pattern (A Gift Wrapper)Sameer Rathoud
 
The Decorator Pattern
The Decorator PatternThe Decorator Pattern
The Decorator PatternAkshat Vig
 
Design Patterns - 01 Introduction and Decorator Pattern
Design Patterns - 01 Introduction and Decorator PatternDesign Patterns - 01 Introduction and Decorator Pattern
Design Patterns - 01 Introduction and Decorator Patterneprafulla
 
Observer and Decorator Pattern
Observer and Decorator PatternObserver and Decorator Pattern
Observer and Decorator PatternJonathan Simon
 
Decorator Design Pattern
Decorator Design PatternDecorator Design Pattern
Decorator Design PatternAdeel Riaz
 

Andere mochten auch (6)

Phani Kumar - Decorator Pattern
Phani Kumar - Decorator PatternPhani Kumar - Decorator Pattern
Phani Kumar - Decorator Pattern
 
Decorator design pattern (A Gift Wrapper)
Decorator design pattern (A Gift Wrapper)Decorator design pattern (A Gift Wrapper)
Decorator design pattern (A Gift Wrapper)
 
The Decorator Pattern
The Decorator PatternThe Decorator Pattern
The Decorator Pattern
 
Design Patterns - 01 Introduction and Decorator Pattern
Design Patterns - 01 Introduction and Decorator PatternDesign Patterns - 01 Introduction and Decorator Pattern
Design Patterns - 01 Introduction and Decorator Pattern
 
Observer and Decorator Pattern
Observer and Decorator PatternObserver and Decorator Pattern
Observer and Decorator Pattern
 
Decorator Design Pattern
Decorator Design PatternDecorator Design Pattern
Decorator Design Pattern
 

Mehr von Abhijit Gaikwad (11)

Java concurrency
Java concurrencyJava concurrency
Java concurrency
 
20 ch22 collections
20 ch22 collections20 ch22 collections
20 ch22 collections
 
17 sessions
17 sessions17 sessions
17 sessions
 
16 cookies
16 cookies16 cookies
16 cookies
 
12 memory hierarchy
12 memory hierarchy12 memory hierarchy
12 memory hierarchy
 
12 cache questions
12 cache questions12 cache questions
12 cache questions
 
10 strategy pattern
10 strategy pattern10 strategy pattern
10 strategy pattern
 
9 abstract interface
9 abstract interface9 abstract interface
9 abstract interface
 
8 polymorphism
8 polymorphism8 polymorphism
8 polymorphism
 
7 inheritance
7 inheritance7 inheritance
7 inheritance
 
4 recursion details
4 recursion details4 recursion details
4 recursion details
 

15 decorator pattern

  • 1. Decorator Pattern Applied to I/O stream classes
  • 2. Design Principle • Classes should be open for extension, but closed for modification – Apply the principle to the areas that are most likely to change
  • 3. Decorator Pattern • Attaches additional responsibilities to an object dynamically. Decorator provides a flexible alternative to subclassing for extending functionality. • Example: StarBuzz Coffee – Several blends • HouseBlend, DarkRoast, Decaf, Espresso – Condiments • Steamed milk, soy, mocha, whipped milk – Extra charge for each – How do we charge all combinations? • First attempt: inheritance
  • 5. <<abstract>> The description instance variable is set in each Beverage subclass and holds a description of the description beverage, like “Java Dark Roast” getDescription() Cost() method is cost() getDescription() method abstract. Subclasses returns the description need to implement their own implementation HouseBlend DarkRoast Decaf Espresso cost() cost() cost() cost() Each subclass implements cost() to return the cost of the beverage
  • 6. Problem with first attempt: • How do we add the condiments? – Apply subclass and inheritance • Add subclasses and inheritance for condiments • But there can be combinations of condiments • Class explosion when all combinations are considered – There must be a better way – Can we treat condiments as instance variables and apply inheritance?
  • 7. <<abstract>> Beverage description: String milk: boolean New boolean values for each condiment soy: boolean mocha: boolean whip: boolean getDescription() We implement cost() in Beverage’s cost() Beverage (instead of cost() calculates the cost of keeping it abstract), so that it condiments. can calculate the costs associated with the The subclasses hasMilk() condiments for a particular calculate the cost of setMilk() beverage instance. the beverage and add Subclasses will still override the cost of condiments hasSoy() cost(), but they also invoke setSoy() the super version to calculate the total cost() of hasMocha() the basic beverage plus the setMocha() costs of the added condiments. hasWhip() setWhip()
  • 9. Decorator1: Any problem? • Our goal is to simplify maintenance. – Prices can change – code change – New condiments – add new methods and alter cost method in superclass – New beverages e.g. tea – Double mocha? • Code changes in the superclass when the above happens or in using combinations
  • 10. Design Principle • Classes should be open for extension, but closed for modification – Apply the principle to the areas that are most likely to change • We want our designs that are resilient to change and flexible enough to take on new functionality to meet changing requirements
  • 11. How? • We want techniques to allow code to be extended without direct modification
  • 12. Start with a beverage and decorate it with condiments at run time • Example: – 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 the condiment costs
  • 13. cost() DarkRoast cost() cost() DarkRoast Mocha cost() cost() cost() 0.10 .20 .99 DarkRoast 1.29 Mocha Whip
  • 14. Decorator Pattern • The Decorator Pattern attaches additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality • See class diagram on the next slide
  • 15. Each component can be used on Component its own, or wrapped by a decorator methodA() component methodB() Each decorator HAS_A (wraps) a component i.e. the decorator has an instance variable that holds a ConcreteComponent Decorator reference to a methodA() component methodA() methodB() methodB() The ConcreteDecorator ConcreteDecoratorA ConcreteDecoratorB has an instance variable Component wrappedObj Component wrappedObj for the thing it decorates (the component the methodA() Object newState Decorator wraps) methodB() methodA() Decorator can add new newBehavior() methodB() methods Can extend state of the component newBehavior()
  • 16. Beverage acts as abstract component component class 4 concrete components, 1 per coffee type The condiment decorators. They need to implement not only cost() but also getDescription()
  • 17. Discussion • It appears that the condimentDecorator is a subclass of Beverage – Really we are subclassing to get the correct type, not to inherit its behavior – When we compose a decorator with a component, we are adding new behavior – Inheritance: the behavior is determined statically at compile time – Composition: we can mix and match decorators any way we like at runtime.
  • 18. More: Inheritance vs composition Inheritance Composition • Need to change • Can implement new existing code any decorators at any time we want new time to add new behavior behavior
  • 19. One more question: • We started with Beverage as an abstract class in Java. Can it be an interface in Java? • Discussion: yes or no? Why?
  • 20. Code Study:Decorator project - Beverage public abstract class Beverage { String description = "Unknown Beverage"; public String getDescription() { // already implemented return description; } public abstract double cost(); // Need to implement cost() }
  • 21. Condiments (Decorator) class We need to be interchangeable with a Beverage, so extend the Beverage class – not to get its behavior but its type public abstract class CondimentDecorator extends Beverage { public abstract String getDescription(); } Here we require all the condiment decorators reimplement the getDescription() method. Explanations coming
  • 22. Coding beverages public class HouseBlend extends Beverage { Note the description public HouseBlend() { variable is inherited description = "House Blend Coffee"; from Beverage. To } take care of description, put this public double cost() { in the constructor for the class return .89; } } Compute the cost of a HouseBlend. Need not worry about condiments
  • 23. Coding condiments Mocha is decorator, so extend CondimentDecorator, which extends Beverage public class Mocha extends CondimentDecorator { Instantiate Mocha with Beverage beverage; a reference to a Beverage using public Mocha(Beverage beverage) { 1. An instance variable this.beverage = beverage; to hold the } beverage we are wrapping public String getDescription() { 2. A way to set this return beverage.getDescription() + ", Mocha"; instance to the } object we are We want the description to wrapping – we pass include the beverage – the beverage we public double cost() { say Houseblend – and the are wrapping to the return .20 + beverage.cost(); condiments } decorator’s Cost of condiment + cost of constructor } beverage
  • 24. public class StarbuzzCoffee { public static void main(String args[]) { Beverage beverage = new Espresso(); // espresso order, no condiments System.out.println(beverage.getDescription() + " $" + beverage.cost()); Beverage beverage2 = new DarkRoast(); // get a DarkRoast beverage2 = new Mocha(beverage2); // wrap it with Mocha beverage2 = new Mocha(beverage2); // warp it with Mocha beverage2 = new Whip(beverage2); // Wrap it with a Whip System.out.println(beverage2.getDescription() + " $" + beverage2.cost()); Beverage beverage3 = new HouseBlend(); // get a Houseblend beverage3 = new Soy(beverage3); // wrap with Soy beverage3 = new Mocha(beverage3); // wrap with Mocha beverage3 = new Whip(beverage3); // wrap with Whip System.out.println(beverage3.getDescription() + " $" + beverage3.cost()); } }
  • 26. Summary 1. CondimentDecorator extends Beverage class – Purpose: the decorators have the same type as the objects they are decorating – Inheritance is used to achieve type matching – Inheritance is NOT used to get behavior 1. Where does the behavior come in? – We acquire behavior not by inheriting from a superclass, but by composing objects together
  • 27. Summary 3. We subclass the abstract class Beverage to have the correct type not to inherit its behavior 4. The behavior comes in through the composition of decorators with the base components as well as other decorators 5. Because we are using object composition, we get a more flexibility about how to mix and match condiments and beverages. 6. Inheritance determines the behavior at compile time. With composition, we can mix and match decorators any way at will at runtime.
  • 28. Summary 7. We started with Beverage as an abstract class in Java. Could it be an interface in Java? Since all we need to inherit is the type of component, we could use an interface in Java.
  • 30. Abstract InputStream component FilterInputStream is an FileInputStream ‘abstract’ decorator StringBufferInputStream FilterInputStream ByteArrayInputStream These InputStreams act as concrete PushBackInputStream components, to be wrapped with decorators Concrete DataInputStream decorators LineNumberInputStream BufferedInputStream Ablity to count line •Buffers input for numbers as it reads data performance •Methods readLine(), mark(), reset()
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37. Writing your own Java I/O decorator • We have learned the decorator pattern • And I/O class diagram • Write a decorator that converts all uppercase characters to lowercase characters in the input stream
  • 38. Extend the FilterInputStream, the abstract decorator for all import java.io.*; inputStream public class LowerCaseInputStream extends FilterInputStream { public LowerCaseInputStream(InputStream in) { super(in); Implement 2 read() methods, taking a } byte (or an array of bytes) and convert each byte to lowercase if it is an public int read() throws IOException { uppercase character int c = super.read(); return (c == -1 ? c : Character.toLowerCase((char)c)); } public int read(byte[] b, int offset, int len) throws IOException { int result = super.read(b, offset, len); for (int i = offset; i < offset+result; i++) { b[i] = (byte)Character.toLowerCase((char)b[i]); } return result; } }
  • 39. import java.io.*; public class InputTest { public static void main(String[] args) throws IOException { int c; Set up fileInputStream and decorate it, first with try { BufferedInputSteam and then InputStream in = LowercaseInputStream filter. new LowerCaseInputStream( new BufferedInputStream( new FileInputStream("test.txt"))); while((c = in.read()) >= 0) { System.out.print((char)c); } in.close(); } catch (IOException e) { e.printStackTrace(); } } }
  • 40. Executing project IO • Test.txt contains “I now know the DECORATOR PATTERN.”