Java中的原型模式-clone()方法
所以,我一直在阅读设计模式,而原型模式让我感到困惑。我认为使用它的一个要点是避免使用新的操作符。然后我看这个例子: 首先,他们的原型思想实现了一个clone()方法,这很奇怪。Wikipedia还说我需要一个纯虚拟的方法克隆来通过子类实现(为什么?)。Java是否已经提供了这样一种方法,它正是我们需要它做的(即创建一个对象的副本,而不是从头开始实例化它)?其次,clone方法调用操作符new!这个例子肯定是错的吗?(在这种情况下,我应该在其他地方研究设计模式,呵呵?)。有人能告诉我这个修正是否正确吗Java中的原型模式-clone()方法,java,design-patterns,clone,cloneable,prototype-pattern,Java,Design Patterns,Clone,Cloneable,Prototype Pattern,所以,我一直在阅读设计模式,而原型模式让我感到困惑。我认为使用它的一个要点是避免使用新的操作符。然后我看这个例子: 首先,他们的原型思想实现了一个clone()方法,这很奇怪。Wikipedia还说我需要一个纯虚拟的方法克隆来通过子类实现(为什么?)。Java是否已经提供了这样一种方法,它正是我们需要它做的(即创建一个对象的副本,而不是从头开始实例化它)?其次,clone方法调用操作符new!这个例子肯定是错的吗?(在这种情况下,我应该在其他地方研究设计模式,呵呵?)。有人能告诉我这个修正是否
static class Tom implements Cloneable implements Xyz {
public Xyz cloan() {
return Tom.clone(); //instead of new I use clone() from Interface Cloneable
}
public String toString() {
return "ttt";
}
}
任何澄清都值得赞赏。设计模式只是一种表示软件如何以可复制的方式编写的方式。事实上,实现同一目标有不同的句法方法 因此,原型模式只是一种使用主副本实现某些覆盖功能的方法。在Java中有几种方法可以做到这一点(我也相信其他语言)。这里有一个使用“new”关键字的方法,它基于使用接口作为实现具体类的契约。然后,单个方法获取接口的具体实现并执行相同的操作:
// software contract
interface Shape {
public void draw();
}
// concrete implementations
class Line implements Shape {
public void draw() {
System.out.println("line");
}
}
class Square implements Shape {
public void draw() {
System.out.println("square");
}
}
...
class Painting {
public static void main (String[] args) {
Shape s1 = new Line ();
Shape s2 = new Square ();
...
paint (s1);
paint (s2);
...
}
// single method executes against the software contract as a prototype
static void paint (Shape s) {
s.draw ();
}
}
您可以在或查看更多信息。这里提供的信息包括完整的参考资料 原型模式的思想是有一个蓝图/模板,您可以从中生成实例。这不仅仅是为了“避免在Java中使用new” 如果您在Java中实现原型模式,那么“是”将完全覆盖对象类中现有的
clone()
方法,而无需创建新方法。(还需要实现可克隆接口,否则会出现异常)
例如:
// Student class implements Clonable
Student rookieStudentPrototype = new Student();
rookieStudentPrototype.setStatus("Rookie");
rookieStudentPrototype.setYear(1);
// By using prototype pattern here we don't need to re-set status and
// year, only the name. Status and year already copied by clone
Student tom = rookieStudentPrototype.clone();
tom.setName("Tom");
Student sarah = rookieStudentPrototype.clone();
sarah.setName("Sarah");
您链接的示例是正确的,您的代码
return Tom.clone();
无法编译,因为clone()
不是静态方法
克隆不是要避免使用new
操作符,而是要创建一个新实例,该实例的状态(其成员字段的值)与被克隆对象的状态相同。因此,clone()
不是静态的,而是一个实例方法,因此您可以创建一个新实例(使用new不是问题),该实例反映了调用了clone()
的对象的状态
只是示例类(如Tom)非常简单(没有状态),因此clone()
方法所做的就是实例化一个新实例。如果它有一个更复杂的状态(比如对象的ArrayList
),那么clone()
方法也必须对ArrayList
进行深度复制
要使用示例类进行详细说明,请假设Tom
具有某些实例状态。现在,clone()
还必须确保返回的副本与当前副本的状态匹配
static class Tom implements Xyz {
private String name;
public Tom() {
this.name = "Tom"; // some state
}
public Xyz clone() {
Tom t = new Tom();
t.setName(getName()); // copy current state
return t;
}
public String toString() {
return getName();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
您还可以使用BeanUtils.copyProperties方法来执行Spring framework org.springframework.beans.BeanUtils提供的相同操作 原型实际上“不”将呼叫保存到
new
操作员。它只是通过调用所谓的克隆
来简化非敏感属性的浅拷贝。比如说,
1) 您有UserAccount
,它有一个主用户和链接的用户详细信息
2) UserAccount
还有一个名为userAccountId
的PK
当然,当您将所有UserAccount
对象放在一个集合中时,您希望userAccountId
不同。但是你仍然需要为你的每个链接调用newuseraccount
。否则,您最终将修改一个对象100次,并期望得到100件东西。此外,如果根据属性的敏感度将此UserAccount
作为组合(而不是聚合),则可能也必须对其调用new
e、 g如果
UserAccount
有Person
对象(如果“Person”有自己的组合),您必须调用new
,以确保它们的引用被适当设置。乍一看,这个实现更像我所期望的。谢谢你指出这一点。我知道实现模式的细节可能会有所不同,但我仍然觉得我链接的模式(可能还有Wikipedia?)有问题。你的意思是,如果类有ArrayList(或任何其他属性),我的clone(或cloan(),在我的例子中)方法会创建一个“new Tom()”然后继续将原型中存储的属性值复制到新对象上?如果是这样,我明白了,问题是这个例子并没有很好地突出原型的有用性。谢谢是的,我就是这个意思。我还添加了一个示例来强调这一点。“利用Cloneable接口中现有的clone()方法”Cloneable
接口中没有clone()
方法如果您在任何地方使用clone方法,您可能会遇到一些棘手的问题。在现实生活中,你必须决定是做深度克隆还是浅层克隆。克隆列表实现或二维数组怎么样?以上是一个非常简单的例子。通常更好的方法是使用副本构造函数来有效地处理这些情况。“我使用可克隆接口中的克隆()”Cloneable接口中没有clone()