Tuesday, April 23, 2019

Decorator Design Pattern

Q- How to write a decorator design pattern in java ?

The decorator pattern is a structural design pattern.
Decorator design pattern is used to add/enhance/modify the functionality of an object at run time without affect the functionality of existing object.
So that we don't need to modify existing class. it is the replacement of inheritance in java.
It is the replacement of inheritance.

The definition of Decorator pattern  provided by Gang of Four book on Design Patterns states:
Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.

In the below code. I have book a room in a hotal and taken some services like news paper, bouquet etc. So this will manage billing for same.


Billing.java 

package com.shubh.design.patern.decorator;

public interface Billing {

 public int getTotalCost();

}


BillingImpl.java 

package com.shubh.design.patern.decorator;

public class BillingImpl implements Billing {

 public int getTotalCost() {
  System.out.println("Basis Cost: " + 100);
  return 100;
 }
}

BillingDecorator.java 

package com.shubh.design.patern.decorator;

public abstract class BillingDecorator implements Billing {

 protected Billing billingInstance;

 public BillingDecorator(Billing billingInstance) {
  this.billingInstance = billingInstance;
 }

 public int getTotalCost() {
  return billingInstance.getTotalCost();
 }
}

BouquetDecorator.java

package com.shubh.design.patern.decorator;

public class BouquetDecorator extends BillingDecorator {

 private Bouquet bouquet;

 public BouquetDecorator(Billing billingInstance, Bouquet bouquet) {
  super(billingInstance);
  this.bouquet = bouquet;
 }

 public int getTotalCost() {
  System.out.println("Bouquet(No. of days:" + bouquet.getNumberOfDay() + ", Cost Per day: "
    + bouquet.getCostPerBouquet() + ") Total Cost = " + getBouquetCost());
  return billingInstance.getTotalCost() + getBouquetCost();
 }

 public int getBouquetCost() {
  return bouquet.getNumberOfDay() * bouquet.getCostPerBouquet();
 }
}

class Bouquet {

 private int numberOfDay;
 private int costPerBouquet;

 public int getNumberOfDay() {
  return numberOfDay;
 }

 public void setNumberOfDay(int numberOfDay) {
  this.numberOfDay = numberOfDay;
 }

 public int getCostPerBouquet() {
  return costPerBouquet;
 }

 public void setCostPerBouquet(int costPerBouquet) {
  this.costPerBouquet = costPerBouquet;
 }
}

NewsPaparDecorator.java

package com.shubh.design.patern.decorator;

public class NewsPaparDecorator extends BillingDecorator {

 private NewsPapar newsPapar;

 public NewsPaparDecorator(Billing billingInstance, NewsPapar newsPapar) {
  super(billingInstance);
  this.newsPapar = newsPapar;

 }

 public int getTotalCost() {
  System.out.println("News Paper(No. of days :" + newsPapar.getNumberOfDay() + ", Cost Per day: "
    + newsPapar.getCostPerDay() + ") Total Cost = " + getNewsPaparCost());
  return billingInstance.getTotalCost() + getNewsPaparCost();
 }

 public int getNewsPaparCost() {
  return newsPapar.getNumberOfDay() * newsPapar.getCostPerDay();
 }
}

class NewsPapar {

 private int numberOfDay;
 private int costPerDay;

 public int getNumberOfDay() {
  return numberOfDay;
 }

 public void setNumberOfDay(int numberOfDay) {
  this.numberOfDay = numberOfDay;
 }

 public int getCostPerDay() {
  return costPerDay;
 }

 public void setCostPerDay(int costPerDay) {
  this.costPerDay = costPerDay;
 }
}


RoomChargeDecorator.java

package com.shubh.design.patern.decorator;

public class RoomChargeDecorator extends BillingDecorator {

 private Room room;

 public RoomChargeDecorator(Billing billingInstance, Room room) {
  super(billingInstance);
  this.room = room;
 }

 public int getTotalCost() {
  System.out.println("Room(No. of days:" + room.getNumberOfDay() + ", Charges Per day: "
    + room.getRoomChargePerDay() + ") Total Cost = " + getRoomCharges());
  return billingInstance.getTotalCost() + getRoomCharges();
 }

 public int getRoomCharges() {
  return room.getNumberOfDay() * room.getRoomChargePerDay();
 }
}

class Room {

 private int numberOfDay;
 private int roomChargePerDay;

 public int getNumberOfDay() {
  return numberOfDay;
 }

 public void setNumberOfDay(int numberOfDay) {
  this.numberOfDay = numberOfDay;
 }

 public int getRoomChargePerDay() {
  return roomChargePerDay;
 }

 public void setRoomChargePerDay(int roomChargePerDay) {
  this.roomChargePerDay = roomChargePerDay;
 }
}

BillingDecoratorMain.java 

package com.shubh.design.patern.decorator;

public class BillingDecoratorMain {

 public static void main(String[] args) {

  NewsPapar newsPaper = new NewsPapar();
  newsPaper.setNumberOfDay(5);
  newsPaper.setCostPerDay(2);

  Bouquet bouquet = new Bouquet();
  bouquet.setNumberOfDay(5);
  bouquet.setCostPerBouquet(150);

  Room room = new Room();
  room.setNumberOfDay(5);
  room.setRoomChargePerDay(1000);

  Billing billing = new NewsPaparDecorator(new BillingImpl(), newsPaper);
  billing = new BouquetDecorator(billing, bouquet);
  billing = new RoomChargeDecorator(billing, room);
  System.out.println("Net Cost To Pay = " + billing.getTotalCost());

 }

}

 
Advantage of Decorator design Pattern in Java.

  • The decorator pattern makes changes easier at run-time.
  • It reduces the number of combination classes.
  • More flexibility than inheritance.
  • In decorator design pattern, responsibilities can be added and removed at run-time
  • We can add any number of decorators in any order as per requirement.
  • It enhance the functionality of object without affecting any other object.

Disadvantage of Decorator design Pattern.

  • There are many number of files to be maintain.

Q- Decorator pattern Vs. Inheritance?
     Inheritance adds responsibility at compile time but decorator pattern adds at run time.

Q- Decorator Design Pattern – UML Diagram?

Q- When to use Decorator Design Pattern?

Example of decorator design patterns used in java API: 

  • java.io.BufferedReader
  • java.io.FileReader
  • java.io.Reader




No comments:

Post a Comment