Decorator Pattern with an Implementation

Decorator design pattern is one of the most important Structural design patterns. As the name suggests this pattern decorates an object by wrapping it.

This pattern dynamically changes the functionality of an object at runtime without impacting the original functionality. We can add or remove functionalities from the Object at runtime. The definition of Decorator provided in the original Gang of Four book on Design Patterns states:

Allows for the dynamic wrapping of objects in order to modify their existing responsibilities and behaviors.

Now what are the ways to change the functionality of an Object?

Extending an object’s functionality can be done statically (at compile time) by using inheritance. So you may consider that sub classing may be the best approach for this. But there will be cases when sub classing isn’t possible, or is impractical.

So, here we are not using inheritance to add functionalities to Objects; instead we are using aggregation.

When to Use It

  • Add responsibilities to individual objects dynamically.
  • Withdraw some responsibility from an Object,
  • When extending a class is impractical like there is no is A relationship. Sometimes, a large number of independent extensions are possible and can create a load of subclasses to support every combination.

Problem Statement:

In our company there are many reward programs for each developer. The awards are given to developers for their achievements at the end of each month with their salary depending on how the developer has performed.

  •   All the developers will get their fixed salary.
  •   Some of the developers can get extra reward for their achievements along with their salary.

Remember, the reward depends on what the developer has done for that month. That means the awards are dynamically added to the developer every month, and they can also be removed the next month.

Implementation

1. We will start with an interface ISalaryService which is actually the blueprint for the decorators.

public interface ISalaryService {
     public String paySalary();
}

2. Now we will provide a concrete implementation of the interface to define the base salary process which will be paid to all developers. This is the base class on which decorators (rewards) will be added.

public class FixedSalary implements ISalaryService
{
    @Override
    public String paySalary()
    {
      return "This is the fixed salary ::";
    }
}

3. Following class is the decorator class. It is the core of decorator design pattern. It has a member of the interface type which is assigned dynamically using the constructor. Once assigned that instance method will be called.

public abstract class SalaryServiceDecorator implements ISalaryService
{
    protected ISalaryService iSalaryService;
    public SalaryServiceDecorator(ISalaryService iss)
    {
        this.iSalaryService = iss;
    }
    @Override
    public String paySalary()
    {
        return iSalaryService.paySalary();
    }
}

4.  Following classes are the decorators. These 2 classes are implementing the abstract decorator to add the reward with fixed salary dynamically.

Here using inheritance is impractical. As there is no is A relationship between reward and salary. We cannot say that CashReward is a FixedSalary, so in place of inheritance we are using aggregation. In the paySalary() method we are adding extra responsibility by calling the methods addCashReward() and addGiftCoupon().

public class CashReward extends SalaryServiceDecorator
{
    public CashReward(ISalaryService ic)
    {
      super(ic);
    }
    public String paySalary()
    {
      return iSalaryService.paySalary() + addCashReward();
    }
    private String addCashReward()
    {
      return " Cash Reward Added to salary ";
    }
}
public class GiftCoupon extends SalaryServiceDecorator
{
    public GiftCoupon(ISalaryService ic)
    {
          super(ic);
    }
    public String paySalary()
    {
      return iSalaryService.paySalary() + addGiftCoupon();
    }
    private String addGiftCoupon()
    {
      return " Gift Coupon Added to salary ";
    }
}

Now let’s test the pattern:

public class TestDecorator {
 public static void main(String args[])
 {
   ISalaryService cashReward = new CashReward(new FixedSalary());
   ISalaryService giftCoupon = new GiftCoupon(new FixedSalary());
   System.out.println(cashReward.paySalary());
   System.out.println(giftCoupon.paySalary());
 }
}
======================================================
Output
======================================================
This is the fixed salary ::  Cash Reward Added to salary
This is the fixed salary ::  Gift Coupon Added to salary

So here we are dynamically changing the behaviour of paySalary() method and adding additional responsibility to add Cash reward and gift coupon with the fixed salary.

How java uses Decorator design pattern:

java.io.* classes use the decorator design pattern. The decorator design pattern attaches responsibilities to objects at runtime. Decorators are more flexible than inheritance because the inheritance attaches responsibility to classes at compile time. The java.io.* classes use the decorator pattern to construct different combinations of behaviour at runtime based on some basic classes.

Consider the following example when we want to open a payslip for a developer.

File file = new File(“c:/payslip_empIdX”);
/*open an inputstream of it */
FileInputStream fis = new FileInputStream(file);
/*We want speed, so let's buffer it in memory */
BufferedInputStream bis = new BufferedInputStream(fis);

At runtime the BufferedInputStream (bis), which is a decorator forwards the method call to its decorated object FileInputStream (fis). The “bis” will apply the additional functionality of buffering around the lower level file (i.e. fis) I/O.

 

CORE JAVA STRUCTURAL-PATTERNS