How to implement Observer pattern in Java?

Photo by Andrea Piacquadio on Pexels.com

Let’s say my blog is gaining popularity.

A lot of people want to be updated with my posts.

And let’s assume that my current blog platform doesn’t provide this option.

So I am writing an application to update my followers.

For now I am considering two types of followers:

  • Email Followers
  • WhatsApp Followers

Whenever I post an article I need to send these followers my post content.

I have decided to use Observer pattern.

Observer pattern lets an object notify any change of its state to all of its followers

This is also popularly called the Publisher-Subscriber pattern.

Let me show you how I have decided to do this.

Here is the client code :

package behavioural.observer.pattern;

public class Client {

	public static void main(String a[]) {

		Blog blog = new TheFullStackDeveloperBlog();

		Follower emailFollower1 = new EmailFollower(blog);
		emailFollower1.setName("The Code Addict");

		Follower emailFollower2 = new EmailFollower(blog);
		emailFollower2.setName("Full Stack Lovers");

		Follower whatsAppFollower = new WhatsAppFollower(blog);
		whatsAppFollower.setName("Tinkerer");

		blog.subscribe(emailFollower1);
		blog.subscribe(emailFollower2);
		blog.subscribe(whatsAppFollower);

		blog.postArticle("How to implement Observer Pattern in Java? .......");

		blog.unsubscribe(emailFollower2);

		blog.postArticle("How to implement Bridge Pattern in Java?....");

	}
}

As you see,

I have created an instance for my blog . This implements the ‘Blog’ interface.

I have created two email followers and one WhatsApp follower.

And all of them are subscribing to my blog.

And then I post an article. This article is then broadcast to all of the three followers.

And then one of them to my dismay unsubscribes from my blog.

I continue posting and post another article.

This time the post is broadcast only to the other two followers.

Let’s see my Blog interface. This is called as ‘Subject’ in Observer pattern:

package behavioural.observer.pattern;

public interface Blog {

	void subscribe(Follower follower);

	void unsubscribe(Follower follower);

	void notifyFollowers();

	void postArticle(String string);

	String getArticle();

}

I have methods to subscribe and unsubscribe to my blog.

And one method to notifyFollowers whenever I post an article.

Another method to do the actual posting of article.

Another method to return the article to the followers.

Here is the implementation .This is called as ‘ConcreteSubject’ .

package behavioural.observer.pattern;

import java.util.ArrayList;
import java.util.List;

public class TheFullStackDeveloperBlog implements Blog {

	List<Follower> followers = new ArrayList<Follower>();

	private String article;

	@Override
	public void subscribe(Follower follower) {

		followers.add(follower);

	}

	@Override
	public void unsubscribe(Follower follower) {

		followers.remove(follower);
	}

	@Override
	public void notifyFollowers() {

		for (Follower follower : this.followers) {

			follower.update();
		}

	}

	@Override
	public void postArticle(String article) {

		this.article = article;

		notifyFollowers();

	}

	@Override
	public String getArticle() {
		return article;
	}

}

As you can see,

I have a list of followers defined.

Every time a follower subscribes , I am adding her to the list.

Every time a follower unsubscribes , I am removing her from the list.

In notifyFollowers() method I iterate through all the followers in the list and call update() method on them.

In postArticle() method I am posting an article and then notifying the followers by calling notifyFollowers() method.

In getArticle() I am returning the article so that followers can read it.

Here is the Follower interface. This is called as ‘Observer’:

package behavioural.observer.pattern;

public interface Follower {

	void update();

	void setName(String name);

}

There are only two methods.

One method update() is called by my blog instance whenever it posts an article.

Another method setName() is used to set a name for the follower.

Here is one of the follower implementation . This is called as ‘ConcreteObserver’:

package behavioural.observer.pattern;

public class EmailFollower implements Follower {

	private String name;

	private Blog blog;

	public EmailFollower(Blog blog) {

		this.blog = blog;

	}

	public String getName() {
		return name;
	}

	public void setName(String name) {

		this.name = name;
	}

	@Override
	public void update() {

		System.out.println();

		System.out.println("Update received by Email Follower: " + this.name);
		System.out.println("New Article posted by The Full Stack Developer:");
		System.out.println(this.blog.getArticle());

	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		EmailFollower other = (EmailFollower) obj;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}

}

As you see , the constructor of EmailFollower takes an argument of the Blog instance.

This is used to read the article later.

There is a method update() which is called by the blog instance when it posts an article.

This method calls getArticle() on the blog instance to read the article.

That’s it.

Here is the output of the client code:


Update received by Email Follower: The Code Addict
New Article posted by The Full Stack Developer:
How to implement Observer Pattern in Java? .......

Update received by Email Follower: Full Stack Lovers
New Article posted by The Full Stack Developer:
How to implement Observer Pattern in Java? .......

Update received by WhatsApp follower: Tinkerer
New Article posted by The Full Stack Developer:
How to implement Observer Pattern in Java? .......

Update received by Email Follower: The Code Addict
New Article posted by The Full Stack Developer:
How to implement Bridge Pattern in Java?....

Update received by WhatsApp follower: Tinkerer
New Article posted by The Full Stack Developer:
How to implement Bridge Pattern in Java?....

As you see, initially three followers are receiving the post content and then after one follower unsubscribes she doesn’t get the update.

You just saw the Observer pattern in action!

Quoting the Gang of Four:

Define a one-to-many dependency between objects so that when one object changes state , all its dependents are notified and updated automatically.

And they suggest to use this pattern when :

– When an abstraction has two aspects , one dependent on the other . Encapsulating these aspects in separate objects lets you vary and reuse them independently (This is not our use case – Here they suggest to break a single class into two if one of the methods is dependent on the other .Then make one class an observer of the other so that when the first class changes the observer class is notified)

– When a change to one object requires changing others , and you don’t know how many object needs to be changed ( Here they suggest that if there are many objects whose state depends on one object’s state change then make them all observers to that object)

– When an object should be able to notify other objects without making assumptions about who these objects are . In other words , you don’t want these objects to be tightly coupled . (As in our case , I don’t want to include instances of every follower in my class to notify them when I post an article)

Here is the code :

https://github.com/vijaysrj/designPatternsGoF/tree/master/src/behavioural/observer/pattern

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