Tutorial

Decorator Design Pattern in Java Example

Published on August 3, 2022
author

Pankaj

Decorator Design Pattern in Java Example

Decorator design pattern is used to modify the functionality of an object at runtime. At the same time other instances of the same class will not be affected by this, so individual object gets the modified behavior. Decorator design pattern is one of the structural design pattern (such as Adapter Pattern, Bridge Pattern, Composite Pattern) and uses abstract classes or interface with composition to implement.

Decorator Design Pattern

We use inheritance or composition to extend the behavior of an object but this is done at compile time and its applicable to all the instances of the class. We can’t add any new functionality of remove any existing behavior at runtime - this is when Decorator pattern comes into picture. Suppose we want to implement different kinds of cars - we can create interface Car to define the assemble method and then we can have a Basic car, further more we can extend it to Sports car and Luxury Car. The implementation hierarchy will look like below image. decorator pattern, decorator design pattern, decorator pattern java But if we want to get a car at runtime that has both the features of sports car and luxury car, then the implementation gets complex and if further more we want to specify which features should be added first, it gets even more complex. Now imagine if we have ten different kind of cars, the implementation logic using inheritance and composition will be impossible to manage. To solve this kind of programming situation, we apply decorator pattern in java. We need to have following types to implement decorator design pattern.

  1. Component Interface - The interface or abstract class defining the methods that will be implemented. In our case Car will be the component interface.

    package com.journaldev.design.decorator;
    
    public interface Car {
    
    	public void assemble();
    }
    
  2. Component Implementation - The basic implementation of the component interface. We can have BasicCar class as our component implementation.

    package com.journaldev.design.decorator;
    
    public class BasicCar implements Car {
    
    	@Override
    	public void assemble() {
    		System.out.print("Basic Car.");
    	}
    
    }
    
  3. Decorator - Decorator class implements the component interface and it has a HAS-A relationship with the component interface. The component variable should be accessible to the child decorator classes, so we will make this variable protected.

    package com.journaldev.design.decorator;
    
    public class CarDecorator implements Car {
    
    	protected Car car;
    	
    	public CarDecorator(Car c){
    		this.car=c;
    	}
    	
    	@Override
    	public void assemble() {
    		this.car.assemble();
    	}
    
    }
    
  4. Concrete Decorators - Extending the base decorator functionality and modifying the component behavior accordingly. We can have concrete decorator classes as LuxuryCar and SportsCar.

    package com.journaldev.design.decorator;
    
    public class SportsCar extends CarDecorator {
    
    	public SportsCar(Car c) {
    		super(c);
    	}
    
    	@Override
    	public void assemble(){
    		super.assemble();
    		System.out.print(" Adding features of Sports Car.");
    	}
    }
    
    package com.journaldev.design.decorator;
    
    public class LuxuryCar extends CarDecorator {
    
    	public LuxuryCar(Car c) {
    		super(c);
    	}
    	
    	@Override
    	public void assemble(){
    		super.assemble();
    		System.out.print(" Adding features of Luxury Car.");
    	}
    }
    

Decorator Design Pattern - Class Diagram

decorator design pattern, decorator design pattern in java

Decorator Design Pattern Test Program

package com.journaldev.design.test;

import com.journaldev.design.decorator.BasicCar;
import com.journaldev.design.decorator.Car;
import com.journaldev.design.decorator.LuxuryCar;
import com.journaldev.design.decorator.SportsCar;

public class DecoratorPatternTest {

	public static void main(String[] args) {
		Car sportsCar = new SportsCar(new BasicCar());
		sportsCar.assemble();
		System.out.println("\n*****");
		
		Car sportsLuxuryCar = new SportsCar(new LuxuryCar(new BasicCar()));
		sportsLuxuryCar.assemble();
	}

}

Notice that client program can create different kinds of Object at runtime and they can specify the order of execution too. Output of above test program is:

Basic Car. Adding features of Sports Car.
*****
Basic Car. Adding features of Luxury Car. Adding features of Sports Car.

Decorator Design Pattern - Important Points

  • Decorator design pattern is helpful in providing runtime modification abilities and hence more flexible. Its easy to maintain and extend when the number of choices are more.
  • The disadvantage of decorator design pattern is that it uses a lot of similar kind of objects (decorators).
  • Decorator pattern is used a lot in Java IO classes, such as FileReader, BufferedReader etc.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the author(s)

Category:
Tutorial

While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
JournalDev
DigitalOcean Employee
DigitalOcean Employee badge
July 14, 2013

Thanks for the nice tutorial.

- Amit

    JournalDev
    DigitalOcean Employee
    DigitalOcean Employee badge
    December 18, 2013

    I want to ask you a question.How did you draw a class diagram? which tool? Could you show some useful UML plugins for eclipse ? Thank you.

    - john

    JournalDev
    DigitalOcean Employee
    DigitalOcean Employee badge
    June 11, 2016

    I use ObjectAid UML Explorer for class diagram. It’s a simple tool and quick to install.

    - Pankaj

      JournalDev
      DigitalOcean Employee
      DigitalOcean Employee badge
      June 10, 2015

      You said: “Now image if we have ten different kind of cars, the implementation logic using inheritance and composition will be impossible to manage” But then you still created 2 classes for each type of car (LuxuryCar & SportsCar). So the this pattern didn’t solve the problem of having ten different kind of cars. Or what did I get wrong here ? Thank you.

      - Muhammad Gelbana

      JournalDev
      DigitalOcean Employee
      DigitalOcean Employee badge
      August 30, 2015

      I believe you will need to use another pattern like the Factory pattern. One drawback to the decorator pattern is that it can add a lot of smaller classes and increase the complexity of the code.

      - Brian Laughlin

        JournalDev
        DigitalOcean Employee
        DigitalOcean Employee badge
        December 10, 2015

        I believe you should put “super.assemble();” instead of “car.assemble();” in concrete decorators. But still your tutorial is great! Thank you very much!

        - ildar

        JournalDev
        DigitalOcean Employee
        DigitalOcean Employee badge
        June 11, 2016

        Thanks for the input, yes you are right. I have corrected it.

        - Pankaj

          JournalDev
          DigitalOcean Employee
          DigitalOcean Employee badge
          February 24, 2016

          Pankaj sir multiple design pattern using create Framework? example login Framework

          - prakash

          JournalDev
          DigitalOcean Employee
          DigitalOcean Employee badge
          June 11, 2016

          Not sure what you meant here.

          - Pankaj

            JournalDev
            DigitalOcean Employee
            DigitalOcean Employee badge
            April 24, 2016

            The relationship between a car and the decorator is inheritance, doesn’t sound quite right to call a CarDecorator “is a” Car.

            - Bal

            JournalDev
            DigitalOcean Employee
            DigitalOcean Employee badge
            June 11, 2016

            CarDecorator has to implement Car interface to provide methods to create Car objects. If you won’t implement Car interface then below code will start giving compile time error.

            Car sportsCar = new SportsCar(new BasicCar());
            

            - Pankaj

              JournalDev
              DigitalOcean Employee
              DigitalOcean Employee badge
              September 5, 2016

              Here inheritance is not used in its usual type "is a " . Here inheritance provides common supertype for car decorator and basic car.

              - Pankaj

                JournalDev
                DigitalOcean Employee
                DigitalOcean Employee badge
                November 17, 2016

                I think CarDecorator should be an abstract class in order for it to confirm to decorator design pattern ,

                - Masoud

                  JournalDev
                  DigitalOcean Employee
                  DigitalOcean Employee badge
                  April 10, 2017

                  Hello. I used your tutorial to implement a Decorator, but found an error: sportsLuxuryCar.assemble(); won’t execute the assemble() method for every Decorator used when creating the instance. So the output of sportsLuxuryCar.assemble(); wont’ be: “Basic Car. Adding features of Luxury Car. Adding features of Sports Car.” but “Basic Car. Adding features of Sports Car.” instead. I think you should correct that in the tutorial, because the chain execution of the assemble() method is useful and should be invoked in constructors in order to work. Thank you!

                  - Agustín Labaronnie

                    JournalDev
                    DigitalOcean Employee
                    DigitalOcean Employee badge
                    May 30, 2017

                    How to print only Luxury Car? Thanks

                    - Arun Singh

                    JournalDev
                    DigitalOcean Employee
                    DigitalOcean Employee badge
                    August 19, 2017

                    new LuxuryCar(new BasicCar());

                    - DEBARATI MAJUMDER

                      JournalDev
                      DigitalOcean Employee
                      DigitalOcean Employee badge
                      May 30, 2017

                      How to get the features of Luxury Car separately if I need them for another car at my home. I assume the same scenario is for Dosa where you can get plain dosa, dosa with masala and dosa with chutney. So masala and chutney classes extend DosaDecorator. PlainDosa class and DosaDecorator class implements Dosa interface. Now what if i want extra chutney (means only chutney separately) ? Thanks in advance.

                      - Arun Singh

                      JournalDev
                      DigitalOcean Employee
                      DigitalOcean Employee badge
                      January 2, 2018

                      Hi Arun, Looks like with Decorator DP it is not possible to get extra chutney. You can’t ask for more aloo or chutney. Actually chutney here is not a separate class, it is dependent on dosa interface. You will have to use some other DP. But you brought the nice question over here. Were you able to figure out the answer to your problem?

                      - Harsh Gupta

                        JournalDev
                        DigitalOcean Employee
                        DigitalOcean Employee badge
                        May 10, 2021

                        Hi Arun, i have implemented as below …will it be fine to get your answer interface Dosa { public void assemble(); } interface Chutney{ public void addChutney(); } class PlainDosa implements Dosa,Chutney{ @Override public void addChutney() { System.out.println(“add extra chutney”); } } class MushroomDosa extends DosaDecorator{ MushroomDosa(Dosa d){ super(d); } public void assemble(){ super.assemble(); PlainDosa plainDosa=new PlainDosa(); plainDosa.addChutney(); System.out.println(“make ready mushroomdosa”); } } suppose i want extry chutney for only mushroomDosa we can go for above code .

                        - nachiketa sahoo

                          Try DigitalOcean for free

                          Click below to sign up and get $200 of credit to try our products over 60 days!

                          Sign up

                          Join the Tech Talk
                          Success! Thank you! Please check your email for further details.

                          Please complete your information!

                          Become a contributor for community

                          Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

                          DigitalOcean Documentation

                          Full documentation for every DigitalOcean product.

                          Resources for startups and SMBs

                          The Wave has everything you need to know about building a business, from raising funding to marketing your product.

                          Get our newsletter

                          Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

                          New accounts only. By submitting your email you agree to our Privacy Policy

                          The developer cloud

                          Scale up as you grow — whether you're running one virtual machine or ten thousand.

                          Get started for free

                          Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

                          *This promotional offer applies to new accounts only.