欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 焦点 > 【观察者】设计模式:构建灵活且响应式的软件系统

【观察者】设计模式:构建灵活且响应式的软件系统

2024/12/23 22:17:02 来源:https://blog.csdn.net/yqq962464/article/details/141958229  浏览:    关键词:【观察者】设计模式:构建灵活且响应式的软件系统

引言

在软件开发中,我们经常面临需要在多个对象之间进行通信的挑战。特别是当一个对象的状态发生变化时,我们希望所有依赖于这个状态的对象都能自动更新。这就是观察者设计模式大显身手的地方。

简介

观察者模式是一种行为设计模式,它定义了对象之间的一对多依赖关系,使得当一个对象状态发生变化时,所有依赖于它的对象都会得到通知并自动更新。

核心组件

  • Subject(主题):也称为Observable,它维护一组观察者,提供添加、删除和通知观察者的接口;
  • Observer(观察者):为所有具体观察者定义一个接口,在得到主题的通知时更新自己;
  • ConcreteSubject(具体主题):保存状态,当状态变化时通知观察者;
  • ConcreteObserver(具体观察者):实现观察者更新接口,以便在主题状态变化时更新自己。

经典实现

// 主题-被观察者
public interface Subject {void registerObserver(Observer observer); //注册观察者void removeObserver(Observer observer); //移除观察者void notifyObservers(Message message); //通知观察者
}
// 观察者
public interface Observer {void update(Message message);
}public class ConcreteSubject implements Subject {private List<Observer> observers = new ArrayList<Observer>();@Overridepublic void registerObserver(Observer observer) {observers.add(observer);}@Overridepublic void removeObserver(Observer observer) {observers.remove(observer);}@Overridepublic void notifyObservers(Message message) {for (Observer observer : observers) {observer.update(message);}}
}//观察者1
public class ConcreteObserverOne implements Observer {@Overridepublic void update(Message message) {//TODO: 获取消息通知,执行自己的逻辑...System.out.println("ConcreteObserverOne is notified.");}
}
//观察者2
public class ConcreteObserverTwo implements Observer {@Overridepublic void update(Message message) {//TODO: 获取消息通知,执行自己的逻辑...System.out.println("ConcreteObserverTwo is notified.");}
}public class Demo {public static void main(String[] args) {ConcreteSubject subject = new ConcreteSubject();subject.registerObserver(new ConcreteObserverOne());subject.registerObserver(new ConcreteObserverTwo());subject.notifyObservers(new Message());}
}

投资理财系统

比如,我们现在在开发一个投资理财系统,用户注册成功后,会给用户发放投资体验金,代码实现大致如下:

public class UserController {private UserService userService; // 依赖注入private PromotionService promotionService; // 依赖注入public Long register(String telephone, String password) {// 注册long userId = userService.register(telephone, password);// 发放体验金promotionService.issueNewUserExperienceCash(userId);return userId;}
}

假如没有扩展修改的需求,那么现在的代码是可以被接受的。如果非得用观察者模式,就会引入更多的类和更加复杂的代码结构,反而是一种过度设计

相反,假如需求频繁改动,比如用户注册成功后,不再发放体验金,而是改为发放优惠券,且给用户发送一封“注册成功”的站内信。此时,就需要频繁修改register函数的代码,违反开闭原则。
而且,如果注册成功后需要执行的后续操作越来越多,那register函数也会越来越复杂,影响代码的可读性和可维护性。

同步阻塞实现

//观察者接口
public interface RegObserver {void handleRegSuccess(long userId);
}//观察者1
public class RegPromotionObserver implements RegObserver {private PromotionService promotionService; // 依赖注入@Overridepublic void handleRegSuccess(long userId) {promotionService.issueNewUserExperienceCash(userId);}
}
//观察者2
public class RegNotificationObserver implements RegObserver {private NotificationService notificationService;@Overridepublic void handleRegSuccess(long userId) {notificationService.sendInboxMessage(userId, "Welcome...");}
}public class UserController {private UserService userService; // 依赖注入private List<RegObserver> regObservers = new ArrayList<>();// 设置观察者public void setRegObservers(List<RegObserver> observers) {regObservers.addAll(observers);}public Long register(String telephone, String password) {long userId = userService.register(telephone, password);//通知观察者for (RegObserver observer : regObservers) {observer.handleRegSuccess(userId);}return userId;}
}

被观察者代码和观察者代码在同一个线程中执行,被观察者代码一直阻塞,直到所有的观察者代码都执行完毕后,才执行后续的代码。
register函数依次调用执行每个观察者的handleRegSuccess函数,都执行完成后,才会返回结果给客户端。

异步非阻塞实现

如果注册接口是一个调用非常频繁的接口,对性能非常敏感,希望接口的响应时间尽可能的短,可以将同步阻塞的实现方式改为异步非阻塞的实现方式,以此来减少响应时间。
register函数执行完成后,启动一个新的线程来执行观察者的handleRegSuccess函数。

跨进程实现

同步阻塞和异步非阻塞都是进程内的实现方式。
而基于消息队列实现的方式则属于一个跨进程的实现方式,观察者和被观察者解耦的更加彻底,两者都感知不到对方的存在。被观察者只管发送消息到消息队列,观察者只管从消息队列中读取消息来执行相应的逻辑。
在这里插入图片描述

总结

观察者模式提供了一种强大的方法来实现对象之间的松耦合通信。它允许系统在不修改现有代码的情况下,通过增加新的观察者来扩展其功能。通过使用观察者模式,我们可以构建出更加灵活、可维护和响应式的软件系统。

参考文献
《极客时间-设计模式之美》

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com