Java 中的原型模式 - clone() 方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17203493/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Prototype Pattern in Java - the clone() method
提问by Leandro Nogueira Couto
So, I've been reading on Design Patterns and the Prototype Patterns confuses me. I believe one of the points of using it is avoiding the need for using the newoperator. Then I look at this example:
所以,我一直在阅读设计模式和原型模式让我感到困惑。我相信使用它的要点之一是避免使用new运算符的需要。然后我看这个例子:
http://sourcemaking.com/design_patterns/prototype/java/1
http://sourcemaking.com/design_patterns/prototype/java/1
First, Their idea of Prototype implements a clone() method, which is weird. Wikipedia also says I need a pure virtual method clone to be implemented by subclasses (why?). Doesn't Java already provide such a method, doing exactly what we need it to do (which is to create a copy of an object instead of instancing it from scratch)? Second, the clone method invokes the operator new! Surely the example is wrong? (In that case I should be studying Design Patterns elsewhere, heh?). Can someone tell if this correction makes it right?:
首先,他们的 Prototype 想法实现了一个 clone() 方法,这很奇怪。维基百科还说我需要一个由子类实现的纯虚方法克隆(为什么?)。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";
}
}
Any clarification is appreciated.
任何澄清表示赞赏。
采纳答案by gerrytan
The idea of prototype pattern is having a blueprint / template from which you can spawn your instance. It's not merely to "avoid using new in Java"
原型模式的想法是拥有一个蓝图/模板,您可以从中生成您的实例。不仅仅是“避免在 Java 中使用 new”
If you implement prototype pattern in Java, then yes by all means override the existing clone()
method from Object class, no need to create a new one. (Also need implement Clonable interface or you'll get exception)
如果您在 Java 中实现原型模式,那么肯定会覆盖clone()
Object 类中的现有方法,无需创建新方法。(还需要实现 Clonable 接口,否则你会得到异常)
As an example:
举个例子:
// 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");
回答by ingyhere
A design pattern is simply a way of representing how software is written in a reproducible way. There are in fact different syntactical approaches to achieving the same thing.
设计模式只是一种表示如何以可重现的方式编写软件的方式。事实上,有不同的句法方法可以实现相同的目标。
So, the Prototype pattern is simply an approach that uses a master copy to implement some overriding functionality. There are several ways to do this in Java (as well, I believe in other languages). Here is one that uses the 'new' keyword, and it's based on using an interface as a contract with implementing concrete classes. Then a single method takes a concrete implementation of the interface and performs the same operation:
因此,原型模式只是一种使用主副本来实现某些覆盖功能的方法。在 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 ();
}
}
You can read more at http://www.javacamp.org/designPattern/prototype.htmlor check out the main Design Pattern site. The information is presented there complete with references.
您可以在http://www.javacamp.org/designPattern/prototype.html 上阅读更多内容,或者查看主要的设计模式站点。信息在那里提供完整的参考资料。
回答by Ravi Thapliyal
The example you've linked is correct and your code
您链接的示例是正确的,您的代码
return Tom.clone();
won't compile because clone()
is not a static method.
不会编译,因为clone()
它不是静态方法。
Cloning is not about avoiding the use of new
operator but creating a new instance that has the same state (values of its member fields) as that of the object that's being cloned. Hence, clone()
is not static but an instance method so that you can create a new instance (and using newisn't a problem) that mirrors the state of the object that clone()
has been invoked upon.
克隆并不是要避免使用new
运算符,而是要创建一个与被克隆对象具有相同状态(其成员字段的值)的新实例。因此,clone()
它不是静态的而是一个实例方法,因此您可以创建一个新实例(并且使用new不是问题),它反映了clone()
已被调用的对象的状态。
It's just that your example classes (like Tom) are so simple (with no state) that all that the clone()
method is doing is to instantiate a newinstance. If it had a bit more complex state (say an ArrayList
of objects) the clone()
method would have to do a deep copy of the ArrayList
as well.
只是您的示例类(如 Tom)非常简单(没有状态),该clone()
方法所做的只是实例化一个新实例。如果它有一个更复杂的状态(比如一个ArrayList
对象),该clone()
方法也必须做一个深拷贝ArrayList
。
To elaborate with one of your example classes, assume that Tom
had some instance state. Now, the clone()
would also have to make sure that the copy being returned matches the state of the current one.
为了详细说明您的示例类之一,假设Tom
有一些实例 state。现在,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;
}
}
回答by Vipul
You can also use BeanUtils.copyProperties method to do the same which is provided by Spring framework org.springframework.beans.BeanUtils;
您还可以使用 BeanUtils.copyProperties 方法来执行由 Spring 框架 org.springframework.beans.BeanUtils 提供的相同方法;
回答by ha9u63ar
Prototype actually "Doesn't"save calls to new
operator. It simply facilitates that a shallow copy of non-sensitive attributes are made by calling the so called clone
. For example,
原型实际上“不”保存对new
操作员的调用。它只是通过调用所谓的clone
. 例如,
1) You have UserAccount
which has a primary user and linked user details
1)你有UserAccount
一个主要用户和链接的用户详细信息
2) UserAccount
also has it's PK called userAccountId
.
2)UserAccount
还有它的 PK 称为userAccountId
.
When you put all your UserAccount
objects in a collection, of course, you would like the userAccountId
to be different. But you still have to call new UserAccount
for each links you have. Otherwise, you will end up modifying one object 100 times expecting 100 things in return. Also, if you have this UserAccount
as a composition (not aggregation) depending on the attribute's sensitivity, you may have to call new
on them too.
当您将所有UserAccount
对象放在一个集合中时,当然,您希望userAccountId
有所不同。但是您仍然需要调用new UserAccount
您拥有的每个链接。否则,您最终将修改一个对象 100 次,期望得到 100 件事的回报。此外,如果您UserAccount
根据属性的敏感性将其作为组合(而不是聚合),您可能也必须调用new
它们。
e.g if UserAccount
has Person
object (and if 'Person' has it's own compositions), you have to call new
to ensure that their references are appropriately set.
例如,如果UserAccount
有Person
对象(如果 'Person' 有它自己的组合),你必须调用new
以确保它们的引用被正确设置。