当前位置: 首页 > news >正文

0124_观察者模式(Observer)

观察者模式(Observer)

意图

定义对象间的一对多依赖关系,当一个对象改变状态时,所有依赖者都会收到通知并自动更新。

UML 图

Observer

优点

  1. 松耦合:主题和观察者之间抽象耦合,彼此不需要知道具体实现
  2. 支持广播通信:一个主题可以通知多个观察者
  3. 开闭原则:可以轻松添加新的观察者而不修改主题
  4. 状态同步:确保所有观察者及时获得状态变化
  5. 职责分离:将观察者与主题的逻辑分离,提高可维护性

缺点

  1. 通知顺序不可控:观察者收到通知的顺序可能不确定
  2. 性能问题:如果观察者数量很多,通知过程可能耗时
  3. 循环依赖:不正确的实现可能导致循环调用
  4. 内存泄漏:如果观察者没有正确注销,可能导致内存泄漏
  5. 过度更新:细小的状态变化可能触发不必要的更新

代码示例

以机器人和人类为例,机器人做饭后通知人类用餐:

1. 观察者接口 (Observer Interface)

// 观察者接口 - 用餐者
public interface MealObserver {void update(String mealName);String getName();
}

2. 主题接口 (Subject Interface)

// 主题接口 - 厨师
public interface CookSubject {void attach(MealObserver observer);void detach(MealObserver observer);void notifyObservers();
}

3. 具体主题 (Concrete Subject)

// 机器人厨师 - 具体主题
public class RobotCook implements CookSubject {private String currentMeal;private List<MealObserver> observers = new ArrayList<>();@Overridepublic void attach(MealObserver observer) {observers.add(observer);System.out.println(observer.getName() + " 开始等待用餐");}@Overridepublic void detach(MealObserver observer) {observers.remove(observer);System.out.println(observer.getName() + " 取消用餐等待");}@Overridepublic void notifyObservers() {System.out.println("🍳 机器人厨师通知: " + currentMeal + " 已准备好!");for (MealObserver observer : observers) {observer.update(currentMeal);}}// 做饭方法public void cookMeal(String mealName) {System.out.println("🤖 机器人开始烹饪: " + mealName);this.currentMeal = mealName;// 模拟烹饪过程try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}mealReady();}private void mealReady() {System.out.println("✅ " + currentMeal + " 烹饪完成!");notifyObservers();}public String getCurrentMeal() {return currentMeal;}
}

4. 具体观察者 (Concrete Observers)

// 人类 - 具体观察者
public class Human implements MealObserver {private String name;public Human(String name) {this.name = name;}@Overridepublic void update(String mealName) {System.out.println("📢 " + name + " 收到通知: " + mealName + " 已准备好!");eat(mealName);}public void eat(String mealName) {System.out.println("🍽️ " + name + " 正在享用: " + mealName);}@Overridepublic String getName() {return name;}
}// 其他类型观察者 - 比如另一个机器人也可以观察
public class OtherRobot implements MealObserver {private String name;public OtherRobot(String name) {this.name = name;}@Overridepublic void update(String mealName) {System.out.println("🔋 " + name + " 收到通知: 开始充电模式");// 机器人可能不需要吃饭,但可以执行其他操作}@Overridepublic String getName() {return name;}
}

5. 客户端代码 (Client Code)

public class ObserverPatternDemo {public static void main(String[] args) {// 创建机器人厨师RobotCook robotCook = new RobotCook();// 创建人类观察者Human john = new Human("John");Human alice = new Human("Alice");Human bob = new Human("Bob");// 创建其他类型观察者OtherRobot helperBot = new OtherRobot("HelperBot");// 注册观察者robotCook.attach(john);robotCook.attach(alice);robotCook.attach(helperBot);System.out.println("\n=== 第一次烹饪 ===");// 机器人开始做饭robotCook.cookMeal("红烧牛肉面");System.out.println("\n=== 调整观察者 ===");// Bob加入等待,Alice取消等待robotCook.attach(bob);robotCook.detach(alice);System.out.println("\n=== 第二次烹饪 ===");// 机器人做另一顿饭robotCook.cookMeal("蔬菜沙拉");}
}

在Java标准库中的应用

观察者模式在Java标准库中有广泛应用:

  1. JavaBeans属性变更监听
// 属性变更支持
public class BeanWithProperty {private String value;private PropertyChangeSupport support = new PropertyChangeSupport(this);public void setValue(String newValue) {String oldValue = this.value;this.value = newValue;support.firePropertyChange("value", oldValue, newValue);}public void addPropertyChangeListener(PropertyChangeListener listener) {support.addPropertyChangeListener(listener);}
}
  1. Swing事件监听
JButton button = new JButton("Click me");
// 添加观察者(事件监听器)
button.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {System.out.println("Button clicked!");}
});
  1. JavaFX属性绑定
SimpleStringProperty name = new SimpleStringProperty("John");
// 观察属性变化
name.addListener((observable, oldValue, newValue) -> {System.out.println("Name changed from " + oldValue + " to " + newValue);
});
  1. Servlet上下文监听
@WebListener
public class AppContextListener implements ServletContextListener {@Overridepublic void contextInitialized(ServletContextEvent sce) {// 应用启动时通知}@Overridepublic void contextDestroyed(ServletContextEvent sce) {// 应用关闭时通知}
}

总结

观察者模式通过定义一对多的依赖关系,实现了对象间的松耦合通信。在机器人做饭通知人类的例子中,机器人作为主题负责状态改变和通知,人类作为观察者接收通知并作出响应。这种模式特别适合需要实现事件通知、状态同步和动态响应的场景,如GUI事件处理、消息推送系统、实时数据更新等。Java标准库中的事件监听机制和属性变更通知都是观察者模式的典型应用。

http://www.hskmm.com/?act=detail&tid=480

相关文章:

  • 读人形机器人07零售行业
  • 你可能不需要WebSocket-服务器发送事件的简单力量
  • 2014年11月微软安全更新风险评估与技术解析
  • 洛谷P5854 【模板】笛卡尔树 题解 笛卡尔树模板题
  • [Flink] Flink 经典场景:数据流输出到多个Sink
  • 都江堰操作系统
  • [OLAP/Doris] Doris 之表设计
  • cmov用法一例
  • 20250909 之所思 - 人生如梦
  • 认识人工智能-基础认知
  • Codeforces Round 1049 (Div. 2)(A~D)
  • 苹果im虚拟机协议群发系统,苹果imessage推信软件,苹果iMessage自动群发协议–持续更新中...
  • 【ChipIntelli 系列】SDK详解4——Makefile 设置 单SDK多工程文件夹实现方法
  • Codeforces Round 1049 (Div. 2)
  • 课前问题思考1
  • huggingface
  • 安全不是一个功能-而是一个地基
  • Python基础-27 match-case 使用教程
  • 从0到1实现Transformer模型-CS336作业1
  • 准备工作之结构体[基于郝斌课程]
  • 软工课程第一次作业
  • java学习起航喽
  • 初始化树莓派(Raspberry Pi)系统并以 ssh 连接教程(只需读卡器、手机开热点,无需显示器) - tsunchi
  • 从windows 自动进入BIOS
  • 软件工程第一次作业
  • Morpheus 审计报告分享:AAVE 项目 Pool 合约地址更新导致的组合性风险
  • Offer发放革命:Moka软件如何将平均入职转化率提升25%
  • U3D动作游戏开发读书笔记--2.1一些通用的预备知识
  • 常见的一些Dos命令
  • AUC和ROC