Skip to main content

Decorator Design Pattern

 

Type : Structural Design Pattern

 

Summary

Decorator Design pattern is used to extend or decorate certain objects statically or at run time.
Multiple Decorator can act on an object to add the desired behavior to a particular object instance without effecting other instances.
Decorator Design pattern is an Structural design pattern, it is alternative to inheritance/ Sub classing in java.
Java sub classing effects all the instances of the class, and some times it is not desirable to do so.


Advantage:

Unlike inheritance, you can choose any single object of a class  leaving the other instances unmodified.

Disadvantage:

Decorator Design Pattern increases the number of Classes in the Application.

Difference between Decorator and Visitor:

Decorator design pattern works on a single object.
Decorator design pattern helps in enhancing a single object with new functionality or behaviour.
Decorator is a Structural design pattern, Visitor is a behavioral design pattern.
Visitor works on composite objects.
Visitor pattern is used to add a new algorithm or functionality to collection of objects or hierarchy of objects.

Details:

Participants:

Component : Interface for object that might have Decorators applied
ConcreateComponent : Concrete objects that implements Component interface
Decorator: Maintains a reference to a Component Object
ConcreateDecorator: Implementations of Decorators that work on the referenced Component object to add behavior to them.

Sample Use Case

This Use Case is with example of Coffee. Let's Say We can have Different type of Coffee in a store with Different Types of Beans, Contents, Size and Price.  One option is to have Different Classes representing different Coffee , say JavaChipsCoffeeTall, JavaChipsWithSugarTall etc. 

In this example we are creating Different Decorators for Different Property of the Coffee to be served. Like for Size of the Coffee can have the following Decorators,

Size Decorators:

CoffeeTallSizeDecorator

CoffeeSmallSizeDecorator

Coffee Type Decorator:

CappuccinoCoffeeDecorator

JavaChipsCoffeeDecorator



Now we can apply a set of Decorators to get our desired cup of Coffee.

Class Diagram



Java Code Sample 

package dp.structural.decorator;

//Decorator Interface
public interface Coffee {

  void brewCofee();

  Double coffeePrice();
}



//Abstract Coffee Decorator
public abstract class CoffeeDecorator implements Coffee {

  private Coffee coffee;

  public CoffeeDecorator(Coffee coffee) {
    this.coffee = coffee;
  }

  public Coffee getCoffee() {
    return coffee;
  }

  public void setCoffee(Coffee coffee) {
    this.coffee = coffee;
  }

  @Override
  public void brewCofee() {
    System.out.println("Cappuccino::: adding raw coffee");
  }

  public Double coffeePrice() {
    return getCoffee().coffeePrice();
  }
}



//CoffeeTallSizeDecorator
public class CoffeeTallSizeDecorator extends CoffeeDecorator {

  public CoffeeTallSizeDecorator(Coffee coffee) {
    super(coffee);

  }


  @Override
  public void brewCofee() {
    getCoffee().brewCofee();
  }

  @Override
  public Double coffeePrice() {
    return getCoffee().coffeePrice() + 3;
  }
}


//JavaChipsCoffeeDecorator
public class JavaChipsCoffeeDecorator extends CoffeeDecorator {

  public JavaChipsCoffeeDecorator(Coffee coffee) {
    super(coffee);
  }

  @Override
  public void brewCofee() {
    // super.brewCofee();
    getCoffee().brewCofee();
    System.out.println("JavaChips:: Adding JavaChips Topping");
  }

  @Override
  public Double coffeePrice() {
    // TODO Auto-generated method stub
    return super.coffeePrice() + 2;
  }
}


//LatteCoffee Decorator
public class LatteCoffeeDecorator extends CoffeeDecorator {
  public LatteCoffeeDecorator(Coffee coffee) {
    super(coffee);
  }

  @Override
  public Double coffeePrice() {
    return getCoffee().coffeePrice() + 10;
  }
}


//Default Coffee
public class DefaultCoffee implements Coffee {

  @Override
  public void brewCofee() {
    System.out.println("### Preparing your coffee  Size :: Small");

  }

  @Override
  public Double coffeePrice() {
    return 1.5;
  }

}

//Demo of the Decorator Design Pattern
public class DecoratorPatternTest {

  public static void main(String[] args) {
    Coffee mycoFfee = new CoffeeTallSizeDecorator(
        new JavaChipsCoffeeDecorator(new CappuccinoCoffeeDecorator(new DefaultCoffee())));
    mycoFfee.brewCofee();
    System.out.println(mycoFfee.coffeePrice());
  }


}


Comments

Popular posts from this blog

Masking Credit Card number in Java

Sometimes we need to mask crucial information like Credit Card Numbers, CVV numbers etc before storing  or logging the information. This example mask Credit Card Number (Except last 4 Digit) from a Text which contains information along with Credit Card Number.

The following example demonstrates how we can easily mask the credit card with Matcher and Pattern Classes. This Sample Code uses Matcher and Pattern.
Pattern Used in this sample is not optimized for Credit Card Numbers, this pattern will get any numerical numbers in the String Content.  Based on the Credit Card Type a more efficient and Strict RegEx can be used to mask the Credit Card.
/**Mask the Credit card number but last four digit value **/   Pattern PATTERN = Pattern.compile("[0-9]+"); String message = content; Matcher matcher = PATTERN.matcher(message); String maskingChar = "*"; StringBuilder finalMask = new StringBuilder(maskingChar); while …

Converting Java Map to String

Java Collections framework, String manipulation etc is something that we often encounter in Development process.
For processing collections (like checking null/empty, Intersection, Disjunction) We do have some of the very use full libraries.

Some of the Collection related libraries are Apche Commons Collections and Google  Collections(Guava).

Problem Use Case

This article explains how to convert a Java Map to String(and vice versa) using different libraries and technique.

One way is to use StringBuilder(Or String) and loop though the Map and build the String by applying some sort of separator ( for key:value and entry). Here we have to take care of the null value etc.

Without Any Library
If we want to convert the map to a String with key value separator and also individual entry seperator in the resulting String, we have to write code for that. For a simple Map, we have to iterate though the map, take care of the null values etc. Following is a sample to get String built out from Map C…

Invoking EJB deployed on a remote machine

Invoking EJB deployed on a remote machineIn case we are calling remote ejb( ejb deployed on remote machines),The JNDI lookup might lookup like,Properties env = new Properties();env.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");env.put(Context.PROVIDER_URL, "XX.XXX.XX.XX:1099");env.put("java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces"); Context ctx = new InitialContext(env);If we are calling local ejb then we can simply create InitialContext without any parameters.Like,Context ctx = new InitialContext();