一.观察者模式介绍与使用场景
观察者模式是一种行为设计模式,用于实现对象之间的发布-订阅机制。在该模式中,存在一个主题对象(被观察者),它维护了一个观察者列表,并在自身状态发生改变时通知所有观察者。观察者对象订阅主题对象的状态变化,并在收到通知后执行相应的操作。
观察者模式通常由以下几个角色组成:
主题(Subject):主题是被观察的对象,它维护了一组观察者,并提供了用于添加、删除和通知观察者的方法。
观察者(Observer):观察者是订阅主题对象的对象,它定义了接收通知和执行相应操作的方法。
观察者模式的核心思想是将主题和观察者解耦,使得它们可以独立变化。主题对象在状态发生变化时,会自动通知观察者对象,而无需观察者主动轮询状态变化。
使用场景:
当一个对象的状态变化需要通知其他对象,并且不希望主动耦合到这些对象时,观察者模式非常有用。通过将观察者注册到主题对象,主题对象在状态变化时会自动通知观察者,而无需观察者主动轮询状态变化。
当一个对象的状态变化可能会引起其他多个对象的更新或处理时,观察者模式可以帮助我们实现对象间的解耦。观察者模式使得主题对象和观察者对象之间的关系变得灵活,可以随时添加、移除或替换观察者,而不影响其他对象的行为。当系统中存在一对多的依赖关系,一个对象的变化需要通知多个对象时,观察者模式能够提供一种简单且可扩展的设计方案。主题对象充当发布者,而观察者对象充当订阅者,它们之间形成了一种松耦合的发布-订阅机制。
当需要在不同层级或模块之间进行消息传递和事件处理时,观察者模式可以帮助我们实现这种通信机制。主题对象作为事件源,观察者对象作为事件处理者,它们之间通过事件通知进行交互。
总结,观察者模式适用于以下情况:
- 一个对象的状态变化需要通知其他对象,并且不希望主动耦合到这些对象。
- 一个对象的状态变化可能会引起其他多个对象的更新或处理。
- 系统中存在一对多的依赖关系,一个对象的变化需要通知多个对象。
- 需要在不同层级或模块之间进行消息传递和事件处理。
通过使用观察者模式,我们可以实现对象间的解耦,提高系统的可维护性和扩展性。同时,观察者模式也符合开闭原则,因为可以动态添加和移除观察者,而无需修改主题对象的代码。
二.观察者模式实现
下面我们用一个简单的demo来描述一下观察者模式:
import java.util.ArrayList; import java.util.List; // 主题 - 被观察者 interface Subject { void registerObserver(Observer observer); void removeObserver(Observer observer); void notifyObservers(); } // 具体主题 - 商品 class Product implements Subject { private List<Observer> observers; private String name; public Product(String name) { this.observers = new ArrayList<>(); this.name = name; } public void setName(String name) { this.name = name; notifyObservers(); } public String getName() { return name; } public void registerObserver(Observer observer) { observers.add(observer); } public void removeObserver(Observer observer) { observers.remove(observer); } public void notifyObservers() { for (Observer observer : observers) { observer.update(this); } } } // 观察者 interface Observer { void update(Subject subject); } // 具体观察者 - 用户 class User implements Observer { private String name; public User(String name) { this.name = name; } public void update(Subject subject) { if (subject instanceof Product) { Product product = (Product) subject; System.out.println(name + " received a notification: " + product.getName() + " is now available."); } } } // 使用示例 public class Main { public static void main(String[] args) { // 创建主题对象 Product product = new Product("iPhone 13"); // 创建观察者对象 User user1 = new User("John"); User user2 = new User("Alice"); // 注册观察者 product.registerObserver(user1); product.registerObserver(user2); // 修改主题状态并通知观察者 product.setName("iPhone 14"); } }
在上述示例中,我们模拟了一个商品发布订阅的场景。主题对象 Product 是被观察的对象,用户对象 User 是观察者。当商品名称发生变化时,主题对象会通知所有观察者对象。
通过 Subject 接口,主题对象提供了注册、移除和通知观察者的方法。具体主题类 Product 实现了主题接口,并维护了观察者列表。在商品名称发生变化时,它会调用 notifyObservers() 方法,遍历观察者列表并调用观察者的 update() 方法。
观察者类 User 实现了观察者接口,并定义了收到通知后的具体操作。在 Main 类的 main 方法中,我们创建了一个商品对象和两个用户对象,并注册用户对象为观察者。当商品名称变化时,观察者会收到通知并执行相应的操作。
通过使用观察者模式,我们能够实现对象之间的松耦合关系,使得主题对象和观察者对象可以独立变化。主题对象无需关心具体的观察者,只需通知它们即可。同时,观察者模式也使得我们能够轻松地添加、移除和管理观察者,以满足动态变化的需求。