Decorator Design Pattern.

What’s is it?

This is design pattern specially targeted for those functionalities which actually needs to be decorated with additional but the same kind of functionality. Consider this example to understand this better,

We are working for School Management system, and in that, we want to calculate salary structure for Staff based on different parameters like work quality, friendliness, punctuality etc. Normally in this scenario, if we try to develop a solution without decorator pattern, we would consider writing if..else conditions with predefined static price values for each salary parameters right? But now if we think further we can easily find out that writing logic this way will not allow us to easily extend our logic further hence, this approach will not make our logic scalable. To fix this, we will use decorator pattern and soon you’ll find out how it helps us to write better scalable code in this context.

Decorator Pattern Class Diagrams.

Implementing Pattern for our problem.

Before we start our implementation, we would need to understand the problem first. So problem is that staff’s salary should be calculated based on the different parameters and each parameter has its own salary points which should be added into the salary to calculate final staff salary, now we also want to offer multiple points calculation so for example, if staff has been given two points for his punctuality, we want to add two times punctuality price bonus to staff’s salary.

Here is the implementation which serves above purpose and just beneath is the explanation of this solution in depth.

package designpatterns.decorator.patterninsinglefile;
/**
*
* @author Milan Z. Savaliya
*/
public class SalaryDecoratorPatternDemo {
	public static void main(String[] args) {
Employee milan = new FullTimeStaff();
milan = new WorkQualityParameter(milan);
milan = new WorkQualityParameter(milan);
milan = new FriendlinessParameter(milan);
milan = new PunctualityParameter(milan);

System.out.println(milan.calculateSalary());
}
}
interface Employee {
	double calculateSalary();
}
class PartTimeStaff implements Employee {
	@Override
public double calculateSalary() {
return 15000;
}
}
class FullTimeStaff implements Employee {
	@Override
public double calculateSalary() {
return 30000;
}
}
interface EmployeeSalaryCalculatorDecorator extends Employee {
abstract String getDescriptionOfQualityParameter();
}
class PunctualityParameter implements EmployeeSalaryCalculatorDecorator {
	Employee employee;
	public PunctualityParameter(Employee Employee) {
this.employee = Employee;
}
	@Override
public String getDescriptionOfQualityParameter() {
return getClass().getSimpleName();
}
	@Override
public double calculateSalary() {
return 1000 + employee.calculateSalary();
}
}
class WorkQualityParameter implements EmployeeSalaryCalculatorDecorator {
	Employee employee;
	public WorkQualityParameter(Employee employee) {
this.employee = employee;
}
	@Override
public String getDescriptionOfQualityParameter() {
return getClass().getSimpleName();
}
	@Override
public double calculateSalary() {
return 1200 + employee.calculateSalary();
}
}
class FriendlinessParameter implements EmployeeSalaryCalculatorDecorator {
	Employee employee;
	public FriendlinessParameter(Employee employee) {
this.employee = employee;
}
	@Override
public String getDescriptionOfQualityParameter() {
return getClass().getSimpleName();
}
	@Override
public double calculateSalary() {
return 600 + employee.calculateSalary();
}
}

Now let’s break down above design pattern into smaller understandable chunks and see how it’s helping us.

Understanding Implemented Decorated Pattern’s Solution.

What we did in the solution is, First, we have created concrete types EmployeePartTimeStaff FullTimeStaff then we created one decorator for salary points calculation which super typed to the interface Employee so that decorator is having the same interface as other Employee types are having. Second, we created concrete decorators for each work quality points and each single object of it represents one single point for final salary calculation.

Then in the demo method, first, we have instantiated an object of FullTimeStaff and assigned it to reference variable of Employee interface, then we decorated that object with WorkQualityParameter two times, then for FriendlinessParameter one time and finally, PunctualityParameter for one time. Finally, we called method calculateSalary() on instance PunctualityParameter and that will call method calculateSalary() of FriendlinessParameter and that will call calculateSalary() method of WorkQualityParameter and that will call calculateSalary() method of second instance of WorkQualityParameter. Chain of execution will look like this,

Findings:-.

I find decorator pattern useful and powerful but it comes with cost of too many small classes which just do the job of decorating other instance for additional functionality.

In Java, java.io package's most of the classes are implemented using this pattern. The solution implemented with this pattern offers much more flexibility and serves us well for long run, but it also cost developer with no idea of decorator pattern of understanding too many classes. But once you understand this pattern very well, you will find it easy to understand package java.io in depth.

You can find more information on “decorator in java.io package" in this StackOverflow article.

https://stackoverflow.com/questions/6366385/decorator-pattern-for-io

Hope you enjoyed this article and found it useful.

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.