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

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.