Refactoring Observer Design Pattern with Lambdas

Many existing object-oriented design patterns can be made redundant or written in a more concise way using lambda expressions.
In this post, I would like to explain how to refactor Observer Design Pattern using lambda expressions?. This post may help in some situations like if we have implemented Observer Design Pattern in our projects using JDK 6 or 7.
Now we want to use JDK 8 then we can refactor implementation of Observer Design Pattern using lambda expressions or we newly implement Observer Design Pattern using lambda expressions in our projects.
Let's understand this refactoring technique with detail example.
You can refer there is a separate post for Observer Design Pattern.
If you want to revise or read the lambda expressions then visit: lambda expressions
The observer design pattern is a common solution when an object (called the subject) needs to automatically notify a list of other objects (called observers) when some event happens (for example, a state change). You typically come across this pattern when working with GUI applications. You register a set of observers on a GUI component such as a button. If the button is clicked, the observers are notified and can execute a specific action. But the observer pattern isn’t limited to GUIs. For example, the observer design pattern is also suitable in a situation where several traders (observers) may wish to react to the change of price of a stock (subject).
Let's refer the above class diagram and write some code to see how the observer pattern is useful in practice. Let's design and implement a customized notification system for an application like Twitter. The concept is simple: several newspaper agencies (NY Times, The Guardian, and Le Monde) are subscribed to a feed of news tweets and may want to receive a notification if a tweet contains a particular keyword.

Observer Pattern: Without  Using Lambda Expressions

Step 1: Create an Observer interface that groups the different observers. It has just one method called inform that will be called by the subject (Feed) when a new tweet is available.
public interface Observer {
     void inform(String tweet);
}
Step 2: Let's create different observers (here, the three newspapers) that produce a different action for each different keyword contained in a tweet.
public class NYTimes implements Observer{
 @Override
 public void inform(String tweet) {
  if(tweet != null && tweet.contains("money")){
   System.out.println("Breaking news in NY!" + tweet);
  }
 }
}

public class Guardian implements Observer{
 @Override
 public void inform(String tweet) {
  if(tweet != null && tweet.contains("queen")){
   System.out.println("Yet another news in London... " + tweet);
  }
 }
}

public class LeMonde implements Observer{
 @Override
 public void inform(String tweet) {
  if(tweet != null && tweet.contains("wine")){
   System.out.println("Today cheese, wine and news! " + tweet);
  }
 }
}
Step 3: Let's Let’s define Subject interface.
public interface Subject{
 void registerObserver(Observer o);
 void notifyObservers(String tweet);
}
Step 4: It’s a pretty straightforward implementation: the feed keeps an internal list of observers that it can then notify when a tweet arrives.
public class Feed implements Subject{
 private final List<Observer> observers = new ArrayList<>();
 public void registerObserver(Observer o) {
  this.observers.add(o);
 }
 public void notifyObservers(String tweet) {
  observers.forEach(o -> o.inform(tweet));
 }
}
Step 5: We can now create a demo application to wire up the subject and observers.
public static void main(String[] args) {
 Feed f = new Feed();
 f.registerObserver(new NYTimes());
 f.registerObserver(new Guardian());
 f.registerObserver(new LeMonde());
 f.notifyObservers("The queen said her favourite book is Java 8 in Action!");
}

Observer Pattern: Using Lambda Expressions

Notice that the different classes implementing the Observer interface are all providing an implementation for a single method: inform().
They’re all just wrapping a piece of behavior to execute when a tweet arrives! Lambda expressions are designed specifically to remove that boilerplate. Instead of instantiating three observer objects explicitly, you can pass a lambda expression directly to represent the behavior to execute:
public static void main(String[] args) {

 Feed feedLambda = new Feed();

 feedLambda.registerObserver((String tweet) -> {
  if(tweet != null && tweet.contains("money")){
   System.out.println("Breaking news in NY! " + tweet); }
 });
 feedLambda.registerObserver((String tweet) -> {
  if(tweet != null && tweet.contains("queen")){
   System.out.println("Yet another news in London... " + tweet); }
 });

 feedLambda.notifyObservers("Money money money, give me money!");

}
Should we use lambda expressions all the time? The answer is no! In the example we described, lambda expressions work great because the behavior to execute is simple, so they’re helpful to remove boilerplate code. But the observers may be more complex: they could have state, define several methods, and the like. In those situations, you should stick with classes.

Related posts


Comments