Java 8

Decorator Pattern using Lambda

Decorator Pattern

A decorator pattern allows a user to add new functionality to an existing object without altering its structure.

Decorator Pattern

Example

BufferedReader buffer = new BufferedReader(new FileReader("file path"));

But rather than being a decorator, this pattern looks ugly.

Using Lambda makes creating a decorator pattern very simple. Let’s look at a very simple example first, before applying the decorator pattern.

import java.util.function.Function


public class Sample {
	public static void print(Integer num, String message, Function<Integer, Integer> func) {
		System.out.println(num + " " + message + ": " + func.apply(num));
	}


	public static void main(String[] args) {
		Function<Integer, Integer> increment = e -> e + 1;
		Function<Integer, Integer> doubled = e -> e * 2;
		print(5, "Incremented", increment);
		print(5, "doubled", doubled);
	}
}

Output

5 Incremented: 6
5 doubled: 10

We can easily call the increment method to increment a number. to double a number we can call the method doubled.

Now lets you want to double a number but increment it first. How are you going to carry this out? One of the answers will be to add a new method incAndThendouble like this.

Function<Integer, Integer> incAndThendouble = e -> (e + 1) * 2;

We may now use the method to get the desired outcome. but this is the incorrect strategy.

The method composition can be used to obtain the desired output that lambda provides out of the box. Let’s explore how to use the method composition.

print(5, "incrented and doubled", increment.andThen(doubled));

Output

5 increented and doubled: 12

Let’s examine how we may use this method’s composition capability to make a Decorator Pattern.

Consider a camera with filters. We could add 0 or more filters to the camera. This is a perfect example of a Decorator Pattern.

import java.awt.Color
import java.util.function.Function;
import java.util.stream.Stream;


class Camera {
	private Function<Color, Color> filter;
	public Camera(Function<Color, Color> ...filters) {
		filter = Stream.of(filters)
					.reduce(Function.identity(),Function::andThen);
	}
	public Color snap(Color input) {
		return filter.apply(input);
	}
}


public class Sample {
	public static void print(Camera camera) {
        //Default color of the snap
		System.out.println(camera.snap(new Color(125, 125, 125)));
	}


	public static void main(String[] args) {

       // Camera with 0 filter
		print(new Camera());

		//Camera with one filter
		print(new Camera(Color::brighter));

        //Camera with two filters
		print(new Camera(Color::brighter, Color::darker));
	}
}
Previous
Next
Pankaj Singh

Specialties: java technologies : Spring, Microservices ,Hibernate, JPA, Apache Spark, Spring Batch, React Js, Maven and Kafka.

Share
Published by
Pankaj Singh

Recent Posts

Strategy Design Patterns using Lambda

Strategy Design Patterns We can easily create a strategy design pattern using lambda. To implement…

2 years ago

Delegating pattern using lambda

Delegating pattern In software engineering, the delegation pattern is an object-oriented design pattern that allows…

2 years ago

Spring Vs Django- Know The Difference Between The Two

Technology has emerged a lot in the last decade, and now we have artificial intelligence;…

2 years ago

TOP 20 MongoDB INTERVIEW QUESTIONS 2022

Managing a database is becoming increasingly complex now due to the vast amount of data…

2 years ago

Scheduler @Scheduled Annotation Spring Boot

Overview In this article, we will explore Spring Scheduler how we could use it by…

2 years ago

Configure Multiple Databases Spring JPA Spring Boot

Overview In this article, we will explore a simple Spring Boot application to implement a…

2 years ago