You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于观察者模式实现Account变更自动持久化的方案咨询

角色划分

首先明确两个模式角色的归属:

  • 被观察者(Observable):Storage<V>抽象基类。所有集合数据的修改逻辑(新增、删除、批量更新等)都封装在这个类中,它是状态变更的唯一源头,天然承担事件发布的职责。
  • 观察者(Observer):独立的变更监听器组件,不要耦合在Storage继承体系里。你需要的自动持久化逻辑就是观察者的一个具体实现,后续如果要加操作日志、远程数据同步、缓存刷新等后置逻辑,只需要新增对应观察者实现即可。
思路合理性评估

这个实现思路完全合理,比硬编码调用save、在Controller层手动触发持久化的方案更健壮:

  • 所有数据变更入口统一收拢在Storage层,不会出现某一处业务代码漏调用save导致内存数据和文件数据不一致的问题。
  • 符合开闭原则,后续扩展变更后置逻辑时不需要修改Storage核心的增删改代码,只需要新增/注册观察者即可。
  • 可以灵活控制持久化触发时机,比如支持批量操作时攒多次变更只触发一次存盘,比每次硬编码调用save更易优化性能。
最小实现代码参考
  1. 首先定义观察者通用接口:
@FunctionalInterface
public interface StorageModifyListener {
    void onModified() throws IOException;
}
  1. 改造Storage<V>抽象类,加入观察者管理和事件通知逻辑:
public abstract class Storage<V>{
    private Set<V> values;
    private String filename;
    private final List<StorageModifyListener> listeners = new ArrayList<>();

    protected Storage(String filename) throws ClassNotFoundException, IOException {
        values = new HashSet<>();
        this.filename = filename;
        // 构造时默认注册持久化监听器,所有子类自动生效
        registerListener(this::persistToFile);
        loadFromFile();
    }

    // 提供监听器注册入口,方便后续扩展其他逻辑
    public void registerListener(StorageModifyListener listener) {
        listeners.add(listener);
    }

    // 数据变更成功后统一通知所有监听器
    private void fireModifyEvent() throws IOException {
        for (StorageModifyListener listener : listeners) {
            listener.onModified();
        }
    }

    public boolean add(V v) throws IllegalArgumentException, IOException {
        if (values.contains(v)) {
            throw new IllegalArgumentException("L'elemento è già presente");
        }
        boolean opSuccess = values.add(v);
        // 仅在操作真正修改了集合时才触发通知,避免无效IO
        if (opSuccess) {
            fireModifyEvent();
        }
        return opSuccess;
    }

    // 其余remove、clear、update等修改集合的方法,都遵循「操作成功后触发fireModifyEvent()」的逻辑即可
    private void persistToFile() throws IOException {
        // 原有序列化写入filename对应文件的逻辑
    }

    private void loadFromFile() throws IOException, ClassNotFoundException {
        // 原有反序列化加载文件数据的逻辑
    }

    // ... 其余查询类方法不需要加通知逻辑
}
注意事项
  • 你目前在Controller层加的synchronized锁可以下沉到Storage的公开修改方法上,避免后续其他业务模块调用Storage时漏加锁,引发并发修改问题。
  • 如果后续有批量导入这类高频修改场景,可以在Storage里加个批量操作的开关,临时关闭事件通知,等批量操作完成后手动触发一次持久化,减少磁盘IO次数。
  • 因为你的Storage子类都是单例实现,注册的监听器只会初始化一次,不会出现重复触发持久化的问题。

内容的提问来源于stack exchange,提问作者MyTech8911

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 05:36:47