如何实现原型模式?

时间:2010-08-20 16:48:57

标签: java design-patterns prototype-pattern

原型模式的目标是通过降低创建成本来克隆对象。 这是一个例子:

class Complex {
    int[] nums = {1,2,3,4,5};
    public Complex clone() {
        return new Complex();//this line create a new object, so is it violate the objective             of prototype ?//
    }
}

class Test2 {
   Complex c1 = new Complex();
   Complex makeCopy() {
      return (Complex)c1.clone();// Is it actually create a new object ? based on the clone method in Complex class? //
   }
   public static void main(String[] args) {
       Test2 tp = new Test2();
       Complex c2 = tp.makeCopy();
   }
}

我认为这是为了深层复制。所以,有人可以帮我解决这个问题吗?

4 个答案:

答案 0 :(得分:1)

首先,要使这个工作正常,您的Complex类需要实现Cloneable标记接口,以指示Object.clone()方法,该方法是合法的,以创建一个字段为字段该类实例的副本。然后,您需要覆盖Object.clone()方法以指定复制行为:

public Complex clone(){
    Complex clone = (Complex)super.clone();
    clone.nums = this.nums;
    return clone;
}

答案 1 :(得分:0)

我不认为给出的示例是按照Prototype Pattern实现的。

我看到的错误是:

  1. 无法克隆标记界面 实现。
  2. 正在使用创建新实例 重写克隆方法中的“new Complex()”构造函数。这个 不应该是这样的。我的意思是说 这里是原型模式我们应该复制一下 来源,做一些改变和 根据要求使用克隆。但不是创建新实例。通过克隆实例创建的成本可以避免,但是如果我们重写克隆方法并创建它自己的实例,你实际上是在增加它的成本。
  3. 了解原型模式的一些链接:

    http://www.javabeat.net/tips/34-using-the-prototype-pattern-to-clone-objects.html

    http://www.allapplabs.com/java_design_patterns/prototype_pattern.htm

答案 2 :(得分:0)

克隆方法的java实现不会调用类构造函数。 它会将当前实例占用的内存复制到内存中的另一个位置。

这种方式真正降低了新对象创建的成本。

答案 3 :(得分:0)

您所说的部分正确,原型模式的目标是降低成本 通过克隆和避免“新”创建对象。

但这并不意味着您可以仅使用该模式来克隆对象。还有其他重要的考虑因素

  • 使用原型对象作为所有其他实例的“制造者”。
  • 从给定的实例原型
  • 创建“几乎”类似的实例

总结一下,原型的目标是:

  • 通过克隆“原型对象”来降低创建对象的成本
  • 当通过原型设计创建的对象与原型对象略有不同时。

下面是一个使用原型PageBanner实例创建不同类型的示例 页面横幅略有不同

 import java.awt.Dimension;
 import java.io.Serializable;

/**
 * This class also acts as a factory for creating prototypical objects.
 */
public class PageBanner implements Serializable, Cloneable  {
   private String slogan;
   private String image;
   private String font;
   private Dimension dimension;

   // have prototype banner from which to derive all other banners
   private static final PageBanner PROTOTYPE = new PageBanner("", 
       "blank.png", "Verdana", new Dimension(600, 45));

   PageBanner(String slogan, String image, String font, 
         Dimension dim)   {
      this.slogan = slogan;
      this.image = image;
      //... other assignments
   }

   // getters and setters..

   public String toString()   {
      return new StringBuilder("PageBanner[")
            .append("Slogan=").append(slogan)
            .append("Image=").append(image)
            .append("Font=").append(font)
            .append("Dimensions=").append(dimension)
            .toString();

   }

   protected Object clone()  {
      Object cln = null;
      try   {
         cln = super.clone();
      }catch(CloneNotSupportedException e)   {
         // ignore, will never happen
      }
      return cln;
   }

   /**
    * This is the creational method that uses the prototype banner 
    * to create banners and changes it slightly (setting slogan and image)
    */
   public static PageBanner createSloganBanner(String slogan, String image)   {
      PageBanner banner = (PageBanner) PROTOTYPE.clone();
      banner.slogan = slogan;
      banner.image = image;
      return banner;
   }

   /**
    * Another creational method that uses the prototype banner 
    * to create banners and changes it slightly (setting image)
    */
   public static PageBanner createImageBanner(String image)   {
      PageBanner banner = (PageBanner) PROTOTYPE.clone();
      banner.image = image;
      return banner;
   }

   // similarly you can have a number of creational methods with 
   // different parameters for different types of banners that 
   // vary slightly in their properties.

   // main... (for illustration)
   public static void main(String[] args) {
      // both these banners are created from same prototypical instance
      PageBanner slogan = PageBanner.createSloganBanner(
            "Stackoverflow Rocks", "stack.png");
      PageBanner img = PageBanner.createImageBanner("stackBanner.png");
   }
}

哦,在你的情况下,让你的原型对象的类实现Cloneable标记接口