Skip to main content

观察者模式 (Observer)

场景问题​

问题案例​

考虑一个微信公众号推送系统,用户可以订阅公众号,公众号发布新消息时,所有订阅用户都会收到通知。

不用模式的解决方案​

实现简化版本​

最直接的做法是公众号对象持有所有用户的引用,发布消息时遍历通知:

public class WeChatOfficialAccount {
private List<User> users = new ArrayList<>();
public void addUser(User user) { users.add(user); }
public void notifyUsers(String message) {
for (User u : users) {
u.receive(message);
}
}
}
public class User {
private String name;
public User(String name) { this.name = name; }
public void receive(String message) {
System.out.println(name + " 收到推送:" + message);
}
}

使用示例​

WeChatOfficialAccount account = new WeChatOfficialAccount();
User u1 = new User("张三");
User u2 = new User("李四");
account.addUser(u1);
account.addUser(u2);
account.notifyUsers("新文章上线");

有何问题​

  1. 用户和公众号耦合度高。
  2. 不能灵活扩展通知方式。
  3. 不能动态添加/移除观察者。

解决方案​

观察者模式的定义​

定义对象间一种一对多的依赖关系,使得每当一个对象状态发生变化时,其相关依赖对象都会收到通知并自动更新。

应用观察者模式的思路​

  • 定义抽象主题(Subject)和抽象观察者(Observer)接口。
  • 主题对象维护观察者列表,状态变化时通知所有观察者。
  • 观察者实现更新接口,接收通知。

观察者模式的结构​

  • Subject:抽象主题,定义维护观察者的方法。
  • ConcreteSubject:具体主题,实现通知逻辑。
  • Observer:抽象观察者,定义更新接口。
  • ConcreteObserver:具体观察者,实现接收通知。

观察者模式的实现​

// 抽象主题
public interface Subject {
void addObserver(Observer o);
void removeObserver(Observer o);
void notifyObservers(String message);
}

// 具体主题
public class WeChatOfficialAccount implements Subject {
private List<Observer> users = new ArrayList<>();
public void addObserver(Observer o) { users.add(o); }
public void removeObserver(Observer o) { users.remove(o); }
public void notifyObservers(String message) {
for (Observer u : users) {
u.update(message);
}
}
}

// 抽象观察者
public interface Observer {
void update(String message);
}

// 具体观察者
public class User implements Observer {
private String name;
public User(String name) { this.name = name; }
public void update(String message) {
System.out.println(name + " 收到推送:" + message);
}
}

使用示例​

public class Client {
public static void main(String[] args) {
WeChatOfficialAccount account = new WeChatOfficialAccount();
User u1 = new User("张三");
User u2 = new User("李四");
account.addObserver(u1);
account.addObserver(u2);
account.notifyObservers("新文章上线");
}
}

观察者重写示例​

示例结构​


示例代码​

见上文"观察者模式的实现"部分。


模式讲解​

观察者模式的功能​

  • 实现对象间的解耦。
  • 支持动态添加、移除观察者。
  • 便于扩展多种通知方式。

实现成接口​

  • 主题和观察者通常定义为接口或抽象类。

使用工厂方法​

  • 可结合工厂方法模式,统一创建主题和观察者对象。

切换产品簇​

  • 可用于切换不同的通知实现,如邮件、短信、推送等。

执行时序图​