How to implement decorator pattern in Java?

Photo by Karolina Grabowska on Pexels.com

Let’s say you are designing a house, an apartment house.

You have done the base design. And now you want to add some more to your design.

Let’s do that using Decorator pattern.

A decorator pattern lets you add responsibilities to an existing object without changing its existing functionality.

An alternate way of achieving this is by adding a subclass for each functionality we want to decorate with.

But that may lead to a large number of sub classes for each decorative functionality.

Also you can’t add a decoration at run time dynamically by sub classing.

Decorator pattern comes to the rescue!

Here is a sample client code using Decorator pattern:

package structural.decorator.pattern;

public class Client {

	public static void main(String a[]) {

		House myhouse = new BalconyDecorator(new KitchenDecorator(new RoomDecorator(new ApartmentHouse())));

		myhouse.design();

		
		System.out.println("New Design");
		
		
		House myhouseAltered = new RoomDecorator(
				new BalconyDecorator(new KitchenDecorator(new RoomDecorator(new ApartmentHouse()))));

		myhouseAltered.design();
	}

}

First I have designed ‘myhouse’.

Here I have created an ApartmentHouse and then kept on adding new things to it. First a plain room through RoomDecorator , then a kitchen using KitchenDecorator and then a balcony using BalconyDecorator.

I have created an alternate design to it (myhouseAltered), by adding one more room to the above design. You can keep adding any decorator any number of times dynamically!

Here is the House interface which we are decorating with :

package structural.decorator.pattern;

public interface House {

	
	public void design();
}

Added just one method “design()”

Now let’s override it in its sub class ‘ApartmentHouse’:

package structural.decorator.pattern;

public class ApartmentHouse implements House {

	@Override
	public void design() {
		
		
		System.out.println("Designing an apartment house");

	}

}

Now let’s keep decorating this apartment house by adding new things. For this we need to create a base abstract Decorator class which also implements ‘House’ interface. Thus both the decorator and the component (house in our case) share the same interface.

Here is the Decorator interface:

package structural.decorator.pattern;

public abstract class HouseDecorator implements House {

	House house;

	public HouseDecorator(House house) {

		this.house = house;
	}

	@Override
	public void design() {

		this.house.design();

	}

}

It is made abstract so that it cannot be instantiated. A default implementation for design() method is given here. It just calls the design method of the house which is passed as a parameter to the decorator’s constructor.

Let’s see one of the concrete decorators , a Room Decorator:

package structural.decorator.pattern;

public class RoomDecorator extends HouseDecorator {

	
	

	public RoomDecorator(House house) {

		super(house);
	}
	
	public void design() {
		
		this.house.design();
		addRoom();
	}
	
	private void addRoom(){
		
		System.out.println("Adding a room");
	}
}

As you can see the design() method of RoomDecorator calls the design method of the house plus adds responsibility to it by “Adding a room”.

We have similar decorator classes for adding a balcony and a kitchen.

Here is the output of the client :

Designing an apartment house
Adding a room
Adding a Kitchen
Adding balcony


New Design
Designing an apartment house
Adding a room
Adding a Kitchen
Adding balcony
Adding a room

Quoting the Gang of Four,

Attach additional responsibilities to an object dynamically.

Decorators provide a flexible alternative to subclassing for extending functionality.

They suggest to use decorator :

– to add responsibilities to individual objects dynamically and transparently , that is , without affecting other subjects

– for responsibilities that can be withdrawn ( in our case , the balcony is not a must for a house)

– when extension by subclassing is impractical . Sometimes a large number of independent extensions are possible and would produce an explosion of subclasses to support every combination. Or a class definition may be hidden or otherwise unavailable for subclassing

Here is the entire code :

https://github.com/vijaysrj/designPatternsGoF/tree/master/src/structural/decorator/pattern


Posted

in

,

by

Comments

Leave a Reply

Discover more from The Full Stack Developer

Subscribe now to keep reading and get access to the full archive.

Continue reading