设计模式剖析系列之原型模式

By heiry on 2019-08-06 [ in 技术 ]

用一个已经创建的实例作为原型,克隆(clone)该原型对象来创建一个和原型相同或相似的新对象,免去创建对象的复杂过程和细节。原型模式分浅拷贝与深拷贝两种。

浅拷贝实现方式:

1.原型类实现CLoneable接口

2.拷贝对象通过原型的clone方法获得新的实例

深拷贝实现方式:

1.原型类实现CLoneable接口

2.原型类重写clone方法,并在克隆对象同时也克隆响应的引用类型成员变量。

————————————–

以下通过国宝熊猫的克隆来理解浅拷贝与深拷贝:

熊猫类包含两个成员属性:熊猫名字与饲养员。熊猫名字为普通字符串对象,饲养员为引用对象。以下分别通过浅拷贝和深拷贝两种方式克隆熊猫对象:

浅拷贝方式:

package net.mosang.prototype;
import java.util.Date;
/**
 * 
 * @author heiry
 *
 */
public class Panda implements Cloneable {
  private String name;
  private Feeder feeder;
  
  //重写clone方法
  @Override
  protected Object clone() throws CloneNotSupportedException {
    Panda panda = (Panda) super.clone();
    return panda;
  }

  //setter、getter
  public String getName() {
    return name;
  }


  public void setName(String name) {
    this.name = name;
  }

  public Feeder getFeeder() {
    return feeder;
  }

  public void setFeeder(Feeder feeder) {
    this.feeder = feeder;
  }


  //构造方法

  public Panda(String name, Feeder feeder) {
    super();
    this.name = name;
    this.feeder = feeder;
  }
  
  }
package net.mosang.prototype;

public class Feeder {
  public String name;
  public void feed() {
    System.out.println("feed panda....");
  }
  public Feeder(String name) {
    super();
    this.name = name;
  }
  
}
package net.mosang.prototype;
public class Client {

  public static void main(String[] args) throws CloneNotSupportedException {
    Feeder feeder = new Feed犀利士
er("张大胖");
    Panda p1 = new Panda("pangpang",feeder);
    Panda p2 = (Panda) p1.clone();
    System.out.println(p1);
    System.out.println(p2);
    feeder.name = "张小胖";
    System.out.println("p1----->"+p1+"p1饲养员:----->"+p1.getFeeder().name);
    System.out.println("p2----->"+p2+"p2饲养员:----->"+p2.getFeeder().name);
  }
}

运行结果:

net.mosang.prototype.Panda@15db9742
net.mosang.prototype.Panda@6d06d69c
p1----->net.mosang.prototype.Panda@15db9742p1饲养员:----->张小胖
p2----->net.mosang.prototype.Panda@6d06d69cp2饲养员:----->张小胖

可见浅拷贝方式,虽然获得了一个与原型对象一样的新对象,但是对于引用类型成员变量feeder,拷贝的是地址而不是对象本身,换句话说,两个对象的feeder指向的是同一个Feeder对象。

深拷贝方式:

重点在于重写原型类的clone方法:

package net.mosang.prototype;
/**
 * 
 * @author heiry
 *
 */
public class Panda implements Cloneable{
  private String name;
  private Feeder feeder;
  
  //重写clone方法,并将引用成员变量feeder同时克隆
  @Override
  protected Object clone() throws CloneNotSupportedException {
    Object obj = super.clone();
    Panda panda = (Panda) obj ;
    panda.feeder = (Feeder)this.feeder.clone();
    return panda;
  }

  //setter、getter
  public String getName() {
    return name;
  }


  public void setName(String name) {
    this.name = name;
  }

  public Feeder getFeeder() {
    return feeder;
  }

  public void setFeeder(Feeder feeder) {
    this.feeder = feeder;
  }
  //构造方法
  public Panda(String name, Feeder feeder) {
    super();
    this.name = name;
    this.feeder = feeder;
  }
  }
package net.mosang.prototype;

public class Feeder implements Cloneable{
  public String name;
  public void feed() {
    System.out.println("feed panda....");
  }
  public Feeder(String name) {
    super();
    this.name = name;
  }
  @Override
  protected Object clone() throws CloneNotSupportedException {
    return super.clone();
  }
  
}

 

package net.mosang.prototype;
public class Client {

  public static void main(String[] args) throws CloneNotSupportedException {
    Feeder feeder = new Feeder("张大胖");
    Panda p1 = new Panda("pangpang",feeder);
    Panda p2 = (Panda) p1.clone();
    System.out.println(p1);
    System.out.println(p2);
    feeder.name = "张小胖";
    System.out.println("p1----->"+p1+"p1饲养员:----->"+p1.getFeeder().name);
    System.out.println("p2----->"+p2+"p2饲养员:----->"+p2.getFeeder().name);
  }
}

运行结果:

net.mosang.prototype.Panda@15db9742
net.mosang.prototype.Panda@6d06d69c
p1----->net.mosang.prototype.Panda@15db9742p1饲养员:----->张小胖
p2----->net.mosang.prototype.Panda@6d06d69cp2饲养员:----->张大胖

可以看到,深拷贝的引用类型成员变量也是各自独立的。

 

 >>



© 2009-2021 MOSANG.NET DESIGNED BY HEIRY