Amit Kumar Mondal bio photo

Amit Kumar Mondal

Java Enthusiast

Email Facebook Google+ LinkedIn Github

Overview

Overview

We have previously seen about implementing Command Pattern using Java 8 Lambda expressions. Now, we would focus on implementing Observer Pattern using the Functional Programming Paradigm in Java 8.

Observer Pattern

</a>

The Problem Domain

The problem is taken from the book Java 8 Lambdas by Richard Warburton.

Let’s discuss about the problem before solving it using Java 8 Lambda Expression.

Nasa has decided to spy on the activities occurring on Moon. So, Nasa needs to build a module to check whether any asteroid or any apollo spacecraft has reached. Nasa needs an effective way so that they can change the module anytime according to their requirements. They might need to extend the module to more spying activities.

OOP way

First of all, I would love to tell you about how it can be achieved using the object oriented way.

Observer

public interface LandingObserver {

	public void observeLanding(String name);

}

Concrete Observer - Apollo

public final class Nasa implements LandingObserver {
	@Override
	public void observeLanding(final String name) {
		if (name.contains("Apollo")) {
			System.out.println("We made it!");
		}
	}
}

Concrete Observer - Asteroid

public final class Aliens implements LandingObserver {

	@Override
	public void observeLanding(final String name) {
		if (name.contains("Apollo")) {
			System.out.println("They're distracted, lets invade earth!");
		}
	}

}

Client

public final class Moon {

	public static void main(final String[] args) {
		final Moon moon = new Moon();
		moon.startSpying(new Nasa());
		moon.startSpying(new Aliens());

		moon.land("An asteroid");
		moon.land("Apollo 11");
	}

	private final List<LandingObserver> observers = Lists.newCopyOnWriteArrayList();

	public void land(final String name) {
		for (final LandingObserver observer : this.observers) {
			observer.observeLanding(name);
		}
	}

	public void startSpying(final LandingObserver observer) {
		this.observers.add(observer);
	}

}

Functional Way

Now let’s move on to the Functional Paradigm

Observer

public interface LandingObserver {

	public void observeLanding(String name);

}

Client

public final class Moon {

	public static void main(final String[] args) {
		final Moon moon = new Moon();

		moon.startSpying(name -> {
			if (name.contains("Apollo")) {
				System.out.println("We made it!");
			}
		});

		moon.startSpying(name -> {
			if (name.contains("Apollo")) {
				System.out.println("They're distracted, lets invade earth!");
			}
		});

		moon.land("An asteroid");
		moon.land("Apollo 11");
	}

	private final List<LandingObserver> observers = Lists.newCopyOnWriteArrayList();

	public void land(final String name) {
		for (final LandingObserver observer : this.observers) {
			observer.observeLanding(name);
		}
	}

	public void startSpying(final LandingObserver observer) {
		this.observers.add(observer);
	}

}

Benefits

Concrete Implementation of the observers have been passed as behavior which eventually made the application more concise and less bloated.