Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中的原型模式-clone()方法_Java_Design Patterns_Clone_Cloneable_Prototype Pattern - Fatal编程技术网

Java中的原型模式-clone()方法

Java中的原型模式-clone()方法,java,design-patterns,clone,cloneable,prototype-pattern,Java,Design Patterns,Clone,Cloneable,Prototype Pattern,所以,我一直在阅读设计模式,而原型模式让我感到困惑。我认为使用它的一个要点是避免使用新的操作符。然后我看这个例子: 首先,他们的原型思想实现了一个clone()方法,这很奇怪。Wikipedia还说我需要一个纯虚拟的方法克隆来通过子类实现(为什么?)。Java是否已经提供了这样一种方法,它正是我们需要它做的(即创建一个对象的副本,而不是从头开始实例化它)?其次,clone方法调用操作符new!这个例子肯定是错的吗?(在这种情况下,我应该在其他地方研究设计模式,呵呵?)。有人能告诉我这个修正是否

所以,我一直在阅读设计模式,而原型模式让我感到困惑。我认为使用它的一个要点是避免使用新的操作符。然后我看这个例子:

首先,他们的原型思想实现了一个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()