进行对象序列化和反序列化而不丢失其侦听器的最佳方法?
时间: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 }