我刚刚学习了原型(prototype)设计模式。
我是一个 Java 人,所以显然我学习了 Java 实现。但我对不同来源的示例实现有些困惑。
我认为这些例子可能是错误的
Prototype Using new
Prototype Using new
上面的示例在其克隆方法实现中使用了 new 关键字。
以下示例很好,因为它完全实现了原型(prototype)定义中所述的实现。
现在,我的问题是,
- 为什么上面两个例子使用了 new 关键字?
- 如果我们使用 new 关键字,那么这种模式的好处不就消失了吗?
- 如果我对上述 2 个示例的理解有误,请在您的回答中说明原因。
- 最后,哪个是正确的实现?为什么?
2013 年 6 月 28 日更新
感谢大家的回答和评论。尽管有些人仍然不明白这里问的是什么。
以上所有作品是实际问题的序言,我一直试图解决的是 我有一个 Cache 对象,其中包含按输入顺序排列的 30K 条目。现在,在用户界面中,我必须根据用户选择以升序或降序显示这些数据。我只能处理缓存对象本身,所以想为什么不使用原型(prototype)模式克隆给定的缓存对象,然后根据用户选择重新排列克隆的缓存对象的内容并向他们显示?
我做出了正确的决定吗? 我不是新运营商的敌人,但在这种特定情况下它不是很昂贵吗? ?
注意
将数据加载到缓存中也不在我手中,也没有任何 UI 端数据操作。
我能做的只是操作预填充的缓存数据。
谢谢米希尔
最佳答案
克隆并不是要避免使用 new
运算符,但创建一个与正在克隆的对象具有相同状态(其成员字段的值)的新实例。
所以,您可以使用clone()
(内部仅使用 new) 或自己创建一个 new 实例(使用复制构造函数或在构造后显式触发 setter )镜像源对象的状态。
在你的第三个例子中
clonedAnimal = (Animal) super.clone();
实际上是在调用Object.clone()
它在此处创建新实例。
另外,尝试删除 clonedAnimal.setXXX()
方法后记,它应该仍然有效,因为默认情况下,Object.clone()
应该已经创建了浅拷贝 。他们可能为了便于理解而将它们留在那里。
编辑:(回应OP的评论)
当你 clone()
你基本上是在委托(delegate) new obj()
调用原始对象本身。
clone()
实现自行承担创建副本的负担。
这就是事情变得有趣的地方。 Object.clone()
是 native 方法。它是在 JVM 中实现的,它执行 C++ 操作来分配堆内存和所有其他爵士乐。但是,当您自己调用 new 运算符时,JVM 所做的事情实际上是相同的(除了复制对象状态之外)。
但是,这不是重点。重要的是要了解何时return super.clone()
将真正返回一个独立克隆对象。即使对于中等复杂的对象,答案也是大多数情况下不,因为它执行浅复制。
因此,如果您的缓存对象占用大量资源,您就必须提供自己的实现来克隆缓存对象。举个例子:假设您的缓存有 LinkedHashMap
最近访问的对象。如果您依赖super.clone()
独自的;您克隆的缓存对象(通过浅拷贝)将仅具有对您的Map的引用的副本,这意味着如果您清除其中一个缓存,另一个缓存也会被清除。
因此,当我说new是通过委托(delegate)clone()
来雇用的;我指的是为克隆提供自己的深复制实现(几乎总是如此)的类。而且,由于他们是在 Java 的范围内执行此操作,因此他们的第一步(除了 Reflection API)是使用 new 运算符实例化一个新对象。
关于java - 原型(prototype)设计模式Java实现困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17314931/