观察者模式(Observer Pattern)是一种行为型设计模式,它定义了一种一对多的依赖关系,允许一个或多个观察者对象订阅主题对象,当主题对象状态发生改变时,会通知所有已订阅的观察者对象,使得它们能够自动更新自己。
主要角色:
Subject(抽象主题、被观察者):
registerObserver() 和 removeObserver())。notifyObservers())。ConcreteSubject(具体主题、具体被观察者):
notifyObservers() 方法通知所有观察者。Observer(抽象观察者):
update())。ConcreteObserver(具体观察者):
update() 方法响应状态的变化,更新自身的状态工作流程:
registerObserver() 方法注册到被观察者。notifyObservers() 方法。update() 方法。update() 方法中根据主题提供的信息或者直接访问主题的状态来进行相应的更新操作。优缺点:
优点:
松耦合:观察者模式实现了主题(被观察者)和观察者之间的松耦合。主题不需要知道观察者的具体类型,只需要通过一个通用的接口进行通知,这有助于降低模块间的耦合度,提高系统的灵活性和可维护性。
扩展性好:增加新的观察者或删除已有的观察者都很方便,只需修改具体的观察者类,对主题和其他观察者没有影响。
响应式编程友好:观察者模式可以很容易地构建基于事件的系统,使得系统具备事件驱动能力,能够及时响应状态变化。
缺点:
如果观察者过多,每次主题状态变化时都需要通知所有的观察者,可能会造成效率低下,尤其是在大型系统中,通知机制可能成为瓶颈。
如果观察者和主题之间存在循环依赖,可能导致系统难以理解和调试。
如果没有良好的设计,可能会出现观察者忘记取消注册而导致内存泄露的情况。
当主题类的状态频繁变化时,会导致大量无谓的通知发送,加大系统的负载。
对于观察者来说,可能会因为不清楚主题的状态何时发生变化,而过度依赖于外部通知,不利于逻辑的清晰性和独立性。
应用场景:
代码示例(以Java为例)
- // 抽象观察者接口
- public interface Observer {
- // 更新方法,当被观察者状态改变时会被调用
- void update(String message);
- }
-
- // 抽象被观察者接口
- public interface Subject {
- // 注册观察者
- void registerObserver(Observer observer);
- // 移除观察者
- void removeObserver(Observer observer);
- // 通知所有观察者
- void notifyObservers(String message);
- }
-
- // 具体被观察者类
- public class ConcreteSubject implements Subject {
- private List
observers = new ArrayList<>(); -
- @Override
- public void registerObserver(Observer observer) {
- observers.add(observer);
- }
-
- @Override
- public void removeObserver(Observer observer) {
- observers.remove(observer);
- }
-
- @Override
- public void notifyObservers(String message) {
- for (Observer observer : observers) {
- observer.update(message);
- }
- }
-
- // 被观察者的状态发生变化时,触发通知
- public void changeState(String newState) {
- System.out.println("Subject state changed to: " + newState);
- notifyObservers(newState);
- }
- }
-
- // 具体观察者类
- public class ConcreteObserver implements Observer {
- private String name;
-
- public ConcreteObserver(String name) {
- this.name = name;
- }
-
- @Override
- public void update(String message) {
- System.out.println(name + " received the following message: " + message);
- }
- }
-
- // 测试类
- public class Main {
- public static void main(String[] args) {
- ConcreteSubject subject = new ConcreteSubject();
-
- Observer observer1 = new ConcreteObserver("Observer 1");
- Observer observer2 = new ConcreteObserver("Observer 2");
-
- subject.registerObserver(observer1);
- subject.registerObserver(observer2);
-
- subject.changeState("New State"); // 改变被观察者状态,此时会触发通知
- }
- }
在这个示例中,ConcreteSubject 类是具体的被观察者,它管理着一个观察者列表。当其状态改变时,会调用 notifyObservers() 方法通知所有已注册的观察者。ConcreteObserver 类是实现了 Observer 接口的具体观察者,当接收到 update() 方法调用时,会做出相应的反应。在 Main 类的测试代码中,我们创建了一个具体的被观察者对象,并添加了两个观察者,然后改变被观察者的状态,可以看到观察者都收到了通知并进行了更新。