我刚学会了原型设计模式。
我是一个Java人,所以很明显我学习了Java实现。但是,对于不同来源的示例实现,我有一些困惑。
我认为这些例子可能是错误的。
使用新的原型
使用新的原型
上面的示例在它们的克隆方法实现中使用了新关键字.
下面的示例很好,因为它正是原型定义中所述的实现。
原型无新
我的问题是,
更新28-06-2013年
谢谢大家的回答和评论。,尽管他们中的一些人仍然不明白这里问了什么。
以上所有工作都是实际问题的序言,我一直试图解决的是,我有一个缓存对象,其中包含30K个条目,按它们输入的顺序排列。现在,在UI中,我必须根据用户选择以升序或降序显示这些数据。我只能处理缓存对象本身,所以我认为为什么不使用原型模式克隆给定的缓存对象,然后根据用户的选择重新安排克隆的缓存对象的内容并显示给它们呢?
我做了正确的决定了吗?我不是新运营商的敌人,但在这种特殊情况下,这样做的代价并不太高。?
备注
我既没有将数据加载到缓存中,也没有任何UI方面的数据操作。
我所能做的只是操作预填充的缓存数据。
谢谢米希尔
发布于 2013-06-26 08:38:21
克隆并不是要避免使用new操作符,而是创建一个新实例,其状态(其成员字段的值)与要克隆的对象的状态相同。
因此,您可以使用clone() (仅在内部使用new ),或者自己创建一个新实例(使用复制构造函数或触发setter显式后构造)来反映源对象的状态。
在第三个例子中
clonedAnimal = (Animal) super.clone();实际上是调用Object.clone(),它在这里创建了新实例。
另外,尝试删除clonedAnimal.setXXX()方法的后缀,它应该仍然工作,因为默认情况下,Object.clone()应该已经创建了一个浅拷贝。他们可能把他们留在那里是为了便于理解。
编辑:(回应OP的评论)
当您使用clone()时,基本上是将new obj()调用委托给原始对象本身。
为什么?所以,它也复制了国家。但是,这并不能保证new没有在一行中使用;只是对象的类公开了一个clone()实现,以承担为自己创建副本的负担。
这是事情变得有趣的地方。Object.clone()是一种本地方法。它是在JVM中实现的,用于分配堆内存和所有其他jazz。但是,当您自己调用新的操作符时(除了复制对象状态),JVM所做的事情实际上是一样的。
但这不是重点。重要的是了解return super.clone()何时真正返回独立的克隆对象。答案是基本上没有,即使对于中等复杂的对象也是如此,因为它做的是浅层复制。
因此,如果缓存对象占用大量资源,则必须为克隆缓存对象提供自己的实现。为了给您举一个例子:让我们假设您的缓存有一个最近访问的对象的LinkedHashMap。如果您仅依赖于super.clone();您的克隆缓存对象(凭借浅表副本)将只拥有对您的Map的引用的副本,这意味着如果您清除您的一个缓存,另一个也将被清除。
因此,当我说new是通过委托给clone()使用的;我指的是为克隆提供自己的深拷贝实现(几乎总是如此)的类。而且,由于它们是在Java的边界内这样做的,所以他们的第一步(禁止反射API)是使用新操作符实例化一个新对象。
发布于 2013-06-26 08:54:29
在Java中,您可以通过两种方式创建对象:通过使用new或通过使用cloneable接口和调用super.clone()。您可能想看看这个问题,它讨论了Java接口。Cloneable本质上是Java自己实现的原型模式。正如它所指出的,克隆接口有几个缺陷。为了避免这种情况,您必须在代码中的某个地方使用new。
cloneable的另一种选择是提供一个副本构造器,即public MyClass(MyClass other) {...。这样做的一个缺点是,您必须声明所创建类型的确切类,原型模式试图阻止这个类。但是,示例1有一个解决方案。
作为对你的例子的评论
doClone,它使客户机不知道实例化的实际类。因此,它不存在上面提到的复制构造函数的缺点。您可以说它是“封装”或隐藏new关键字。super.clone()。然而,它也会让克隆界面的问题变得有趣。我个人的观点是,第一种方案似乎是较好的解决方案,尽管我从未彻底地使用过原型模式或可克隆的接口。
https://stackoverflow.com/questions/17314931
复制相似问题