我需要复制一个具有相当深的成员变量层次结构的对象(即,该对象具有多个不同类型的成员,每个成员具有多个不同类型的成员,等等)。执行深层复制需要在许多类中实现clone()方法,这对我的应用程序来说似乎有点过分了。
我提出的解决方案相当简单,但我想知道这是不是一个坏主意。我的解决方案如下:
Settings
。IsCopyable
的界面,该界面包含方法getSettings()
和applySettings(Settings s)
。X
的给定类IsCopyable
,将编写一个实现接口Settings
的类,其中包含必须应用于类{{}对象的“设置”。 1}}以便复制它。 (我通常在课程X
中嵌套这个课程,所以我有X
,但这可以在其他地方完成。)然后,复制类X的实例:
X.Settings implements Settings
即,要复制给定对象,请创建该对象的新实例,然后在要复制的对象上调用X myX = new X();
// Stuff happens to myX.
// Now we want to copy myX.
X copyOfX = new X();
copyOfX.applySettings(myX.getSettings());
,将生成的getSettings()
对象作为值传递给{{1}在新实例上。 (当然,复制可以包含在名为copy()或其他东西的成员中。)
这对我的特定问题非常有效,但我做的事情是愚蠢的吗?我(很差)重新发明了已经存在的东西吗?
提前致谢。
克里斯
答案 0 :(得分:3)
答案 1 :(得分:1)
这可能是代码味道,您可能需要采取另一种方法。 您的对象应该“显然是可复制的”,有几种方法可以创建这种类型的对象:
我不太了解你的设计是否告诉你它是否是最好的解决方案,但一般我所做的是创建一个工厂,这只是一个“包属性”来创建我的对象,然后我实现ICloneable在工厂。
答案 2 :(得分:0)
您可以使用ICloneable界面,这里有一个解释http://blog.reamped.net/post/2008/03/Implementing-Interfaces-ICloneable-and-IComparable.aspx
答案 3 :(得分:0)
我目前遇到类似情况,我必须复制asp.net的客户服务器控件。问题在于,由于复杂的控制层次结构,使用MemberwiseClone()进行克隆会产生一些不良影响。
我还不知道如何解决这个问题,但我有一些想法是实现ICloneable接口,但没有使用MemberwiseClone()
而是创建一个新的实例,如
public class MyObject : ICloneable
{
...
public object ICloneable.Clone()
{
MyObject clone = new MyObject();
//copy everything I want to have from this object to the clone
return clone;
}
}
然后你打电话
MyObject someObjInstance = new MyObject();
...
...
MyObject clone = ((ICloneable)someObjInstance).Clone();
...
您将获得一个全新的对象,其中包含您需要的复制成员。我没有看到您提到的设置的好处,因为实现Clone()
的类将知道要复制的内容。
这取决于您当然的具体目的。这将意味着创建新实例,而不是像MemberwiseClone()
那样进行逐位复制。
答案 4 :(得分:0)
如果您的界面Settings
为空(没有属性或方法),我会称之为代码味道。按照惯例,接口应以字母“I”或ISettings
开头。
您如何实施方法applySettings(Settings s)
?正如您所说,Settings
接口为空,除非您将其转换为其他对象,否则您无法对s
参数执行任何操作。这很糟糕,或者更好地描述为“无意义”,因为参数是强类型的,但忽略了强类型。
此外,我认为没有充分理由采用applySettings()
方法。如果您有一个对象,并且第二个对象具有您需要的值,则只需使用第二个对象。如果正在使用第二个对象(在某些其他对象图中),则复制它并使用它。应该没有理由编写“使此对象成为另一个对象的副本”的逻辑,因为您必须已经编写了“制作副本”。
从客户的角度来看,制作深层副本应该很容易。 ICloneable
界面非常适合这种情况。作为设计模式,这被称为 Prototype 模式。如果您需要不同的方法来创建副本(即不同类型的深层复制操作),您可以考虑使用构建器模式来实现Clone()
方法