【发布时间】:2014-07-16 13:48:34
【问题描述】:
TL;DR
我可以通过Serializable 接口、ObjectOutputStream 和ObjectInputStream 类使用Java 序列化/反序列化,并且可能在实现Serializable 的类中添加readObject 和writeObject 作为原型模式的有效实现或不是吗?
注意
这个问题不是讨论使用复制构造函数是否比序列化/反序列化更好。
我知道Prototype Pattern 概念(来自维基百科,强调我的):
原型模式是软件开发中的一种创造设计模式。当要创建的对象类型由原型实例确定时使用,该实例被克隆以生成新对象。此模式用于:
避免在客户端应用程序中使用对象创建者的子类,就像抽象工厂模式一样。
避免以标准方式(例如,使用“new”关键字)创建新对象的内在成本,因为它对于给定的应用程序来说过于昂贵。
从这个 Q/A:Examples of GoF Design Patterns in Java's core libraries,BalusC 解释说,Java 中的原型模式只有在类实现 Cloneable 接口时才由 Object#clone 实现(标记接口类似于 Serializable 以序列化/反序列化对象) .使用这种方法的问题在博客文章/相关 Q/As 中有所说明,如下所示:
因此,另一种选择是使用复制构造函数来克隆您的对象(DIY 方式),但这无法实现我上面强调的文本的原型模式:
避免以标准方式创建新对象的固有成本(例如,使用“new”关键字)
AFAIK 在不调用其构造函数的情况下创建对象的唯一方法是通过反序列化,如该问题的已接受答案示例中所述:How are constructors called during serialization and deserialization?
所以,我只是问是否通过ObjectOutputStream 使用对象反序列化(并且知道您在做什么,将必要的字段标记为transient 并了解此过程的所有含义)或类似的方法将是原型模式的正确实现。
注意:我不认为解组 XML 文档是这种模式的正确实现,因为它调用了类构造函数。可能在解组 JSON 内容时也会发生这种情况。
人们会建议使用对象构造函数,并且在使用简单对象时我会介意该选项。这个问题更倾向于深度复制复杂的对象,我可能有 5 个级别的对象要克隆。例如:
//fields is an abbreviation for primitive type and String type fields
//that can vary between 1 and 20 (or more) declared fields in the class
//and all of them will be filled during application execution
class CustomerType {
//fields...
}
class Customer {
CustomerType customerType;
//fields
}
class Product {
//fields
}
class Order {
List<Product> productList;
Customer customer;
//fields
}
class InvoiceStatus {
//fields
}
class Invoice {
List<Order> orderList;
InvoiceStatus invoiceStatus;
//fields
}
//class to communicate invoice data for external systems
class InvoiceOutboundMessage {
List<Invoice> invoice;
//fields
}
假设我想要/需要复制InvoiceOutboundMessage 的实例。我认为复制构造函数不适用于这种情况。在这种情况下,拥有大量复制构造函数的 IMO 似乎不是一个好的设计。
【问题讨论】:
-
我严重怀疑任何从原型创建对象的方案在时间或空间上都比简单地使用合理适当的构造函数更有效。
-
推荐使用复制构造函数的原因是,使用任何其他方式(不调用任何构造函数)可能会导致某些类失败(本应唯一的标识符突然出现重复,等等)。我建议坚持使用复制构造函数,因为它们是在 Java 中复制对象的安全、常规方式。
-
@HotLicks 问题已更新。
-
@Chronio 我的问题根本不是关于复制构造函数的。我想知道对象反序列化是否是实现原型模式的另一种选择。而且你没有在你的 cmets 中解决这个问题。是的,我有大对象要复制,由于系统维护,哪些字段可能会因周期而异。在这种情况下,更新大量可以加速应用程序以在 0.582 毫秒内(例如)获得深拷贝的类并不比使用对象序列化/反序列化更好谁向我展示了几乎那么快,就像 JIT 没有启动时的 1.042 毫秒。
-
@HotLicks 我没有为任何事情辩解。我只是想知道这是否是原型模式的有效实现。如果您非常确定自己的答案,请发布。
标签: java design-patterns serialization deserialization prototype-pattern