What is Observer Pattern?
Observer pattern is a behavioral pattern that defines a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified and updated automatically.
The object changes state is called Subject, and its dependents are called Observers.
When to use it?
You can use Observer pattern when you need one-to-many dependency between objects, the one will change its state and the many dependents need to keep track of those changes.
Let's assume we use SNS like X(Twitter), companies and people have their own account, and people can follow their favorite company so that they want notification when the company post about new item or sale item. In this situation, Observer pattern is applicable.
UML diagram
Example UML diagram
- When
setSaleItem
method is called, that is, the state is changed, we callsetItemChanged
method. Then,setItemChanged
method callsnotifyAccount
method. -
notifyAccount
method in Company class iterates eachfollower
and callupdate
method with its own Company object such asfollower.update(this)
Implementation in Java
ICompany interface:
public interface ICompany {
void registerAccount(IAccount account);
void removeAccount(IAccount account);
void notifyAccounts();
}
Company class:
import java.util.ArrayList;
import java.util.List;
public class Company implements ICompany {
private List<IAccount> followers;
private String name;
private String saleItem;
public Company(String name) {
followers = new ArrayList<>();
this.name = name;
}
@Override
public void registerAccount(IAccount account) {
this.followers.add(account);
}
@Override
public void removeAccount(IAccount account) {
this.followers.remove(account);
}
@Override
public void notifyAccounts() {
for (IAccount follower : followers) {
follower.update(this);
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSaleItem() {
return saleItem;
}
public void setSaleItem(String saleItem) {
this.saleItem = saleItem;
saleItemChanged();
}
public void saleItemChanged() {
notifyAccounts();
}
}
IAccount interface:
public interface IAccount {
void update(Company company);
}
Account class:
public class Account implements IAccount {
private String name;
public Account(String name) {
this.name = name;
}
@Override
public void update(Company company) {
System.out.println(this.name + " receives a new message from " + company.getName());
System.out.println("New sale item: " + company.getSaleItem());
}
}
Client class:
public class Client {
public static void main(String[] args) {
Company apple = new Company("Apple"); // concrete subject
IAccount john = new Account("John");
IAccount david = new Account("David");
// John starts following Apple Inc.
apple.registerAccount(john);
apple.setSaleItem("iPhone 14");
System.out.println("**********************");
// David becomes a new follower to Apple Inc.
apple.registerAccount(david);
apple.setSaleItem("iPad");
System.out.println("**********************");
// John doesn't receive message from Apple Inc. as he deregistered for Apple Inc.
apple.removeAccount(john);
apple.setSaleItem("AirPods");
}
}
Output:
John receives a new message from Apple
New sale item: iPhone 14
**********************
John receives a new message from Apple
New sale item: iPad
David receives a new message from Apple
New sale item: iPad
**********************
David receives a new message from Apple
New sale item: AirPods
You can check all the design pattern implementations here.
GitHub Repository
P.S.
I'm new to write tech blog, if you have advice to improve my writing, or have any confusing point, please leave a comment!
Thank you for reading :)
Top comments (0)