进行对象序列化和反序列化而不丢失其侦听器的最佳方法?

时间:2020-03-06 14:42:26  来源:igfitidea点击:

我有一个可注册监听器的可序列化对象。当前,侦听器列表以"瞬态"形式存储在对象中。当对象被序列化然后反序列化时,显然不再注册侦听器。

一旦对象反序列化,自动重新注册侦听器的最安全,最佳方法是什么?有没有一个好的设计模式对我们有帮助?

解决方案

我们可以使用既充当事件的侦听器又充当事件的广播器的代理对象,并为其分配实际的侦听器,然后将其分配为要序列化的对象的侦听器。序列化然后反序列化时,只需将其重新分配为反序列化对象的侦听器即可。

我将建立一个解耦的事件框架,这意味着事件生产者将不会直接绑定到事件使用者。
它可以由一个EventManager,一个EventProducer和一个EventListener与发布/预订语义一起使用。

  • 系统启动时(或者首次使用时),将创建一个EventManager。
  • EventListener进行注册以接收特定类型的事件。
  • EventProducer产生事件并将其发布到EventManager
public interface EventManager {
        public void postEvent(Event event);
        public void addListener(Class eventType, EventListener listener);
    }

    public interface EventListener {
        public void handleEvent(Event event);
    }

这样,当序列化生产者时,EventManager仍会维护已订阅侦听器的列表。反序列化对象时,它仍然可以将事件发布到EventManager。

总的来说,我没有意识到任何有用的模式。但是将几个结合起来就可以了:)。问题是我们如何处理反序列化?如果使用标准方式,则可以引入查找机制,该机制将用于定位本地侦听器并将其重新绑定到新的反序列化实例。如果我们有自己的解串器,则方法会更简单。只需反序列化对象并注册本地侦听器即可。如果可能,解串器可以充当代理侦听器。正如Panagiotis所说,引入一些解耦模型也将有所帮助。确切的解决方案取决于实际需求,但请不要忘记亲吻它。

使用发布者和订阅者都向其注册的注册表。正如科罗斯(Korros)发布的那样,它在OSGI领域被称为"白板模式"。

如果实现readObject(),则可以将瞬时状态重建为反序列化的一部分。我们应该将反序列化视为对象构造(因为确实如此)。

private void readObject(ObjectInputStream in) 
       throws ClassNotFoundException, IOException {
     // do normal serialization first!
     in.defaultReadObject();

     // put code here that can somehow reconstruct your listeners
     // presumably you have someplace you can look them up
  }