Java中的Prototype Pattern - clone()方法

时间:2013-06-20 00:25:48

标签: java design-patterns clone cloneable prototype-pattern

所以,我一直在阅读设计模式,原型模式让我困惑。我相信使用它的一个要点是避免使用 new 运算符。然后我看一下这个例子:

http://sourcemaking.com/design_patterns/prototype/java/1

首先,他们对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";
    }
  } 

任何澄清都表示赞赏。

5 个答案:

答案 0 :(得分:9)

原型模式的想法是有一个蓝图/模板,您可以从中生成您的实例。它不仅仅是“避免在Java中使用新的”

如果在Java中实现原型模式,则无论如何都是覆盖Object类中的现有clone()方法,无需创建新方法。 (还需要实现Clonable接口或者你会得到异常)

举个例子:

// 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");

答案 1 :(得分:4)

设计模式只是表示软件如何以可重现的方式编写的一种方式。事实上,实现同样的事情有不同的句法方法。

因此,Prototype模式只是一种使用主副本来实现某些重写功能的方法。在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 ();
   }
}

您可以在http://www.javacamp.org/designPattern/prototype.html阅读更多内容或查看main Design Pattern site。信息在那里提供完整的参考。

答案 2 :(得分:3)

您链接的示例是正确的,您的代码

return Tom.clone();

将无法编译,因为clone()不是静态方法。

克隆不是避免使用new运算符,而是创建一个与正在克隆的对象具有相同状态(其成员字段的值)的新实例。因此,clone()不是静态的,而是实例方法,因此您可以创建一个新实例(并使用 new 不是问题),它反映了{{1的对象的状态已被调用。

只是你的示例类(如Tom)非常简单(没有状态),clone()方法所做的就是实例化一个 new 实例。如果它有一个更复杂的状态(比如clone()个对象),ArrayList方法也必须对clone()进行深层复制。

要详细说明您的一个示例类,假设ArrayList有一些实例状态。现在,Tom还必须确保返回的副本与当前副本的状态匹配。

clone()

答案 3 :(得分:0)

您也可以使用BeanUtils.copyProperties方法执行Spring框架org.springframework.beans.BeanUtils提供的相同操作;

答案 4 :(得分:0)

原型实际上“没有” 将呼叫保存到new运算符。它只是通过调用所谓的clone来简化非敏感属性的复制。例如,

1)您有UserAccount,该用户具有主要用户和链接的用户详细信息

2)UserAccount的PK也称为userAccountId

当然,当您将所有UserAccount对象放入一个集合中时,您希望userAccountId是不同的。但是您仍然必须为每个链接调用new UserAccount。否则,您最终将修改一个对象100次,并期望得到100项回报。另外,如果根据属性的敏感度将此UserAccount作为组合(不是聚合),则可能也必须对其调用new

例如,如果UserAccount具有Person对象(并且如果'Person'具有其自己的构成),则必须调用new以确保适当地设置了它们的引用。