基于观察者模式实现Account变更自动持久化的方案咨询
角色划分
首先明确两个模式角色的归属:
- 被观察者(Observable):
Storage<V>抽象基类。所有集合数据的修改逻辑(新增、删除、批量更新等)都封装在这个类中,它是状态变更的唯一源头,天然承担事件发布的职责。 - 观察者(Observer):独立的变更监听器组件,不要耦合在Storage继承体系里。你需要的自动持久化逻辑就是观察者的一个具体实现,后续如果要加操作日志、远程数据同步、缓存刷新等后置逻辑,只需要新增对应观察者实现即可。
思路合理性评估
这个实现思路完全合理,比硬编码调用save、在Controller层手动触发持久化的方案更健壮:
- 所有数据变更入口统一收拢在Storage层,不会出现某一处业务代码漏调用save导致内存数据和文件数据不一致的问题。
- 符合开闭原则,后续扩展变更后置逻辑时不需要修改Storage核心的增删改代码,只需要新增/注册观察者即可。
- 可以灵活控制持久化触发时机,比如支持批量操作时攒多次变更只触发一次存盘,比每次硬编码调用save更易优化性能。
最小实现代码参考
- 首先定义观察者通用接口:
@FunctionalInterface public interface StorageModifyListener { void onModified() throws IOException; }
- 改造
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
相关产品推荐
相关产品推荐

