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

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

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

浅拷贝实现方式:

1.原型类实现CLoneable接口

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

深拷贝实现方式:

1.原型类实现CLoneable接口

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

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

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

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

浅拷贝方式:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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; 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;
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;
  }
  
  }
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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 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 Feeder {
  public String name;
  public void feed() {
    System.out.println("feed panda....");
  }
  public Feeder(String name) {
    super();
    this.name = name;
  }
  
}
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
package net.mosang.prototype;
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
Feeder feeder = new Feed<span style="font-size:0px; color:#ff0000;"><a href="https://www.cialisrr.com/">犀利士</a>
</span>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);
}
}
package net.mosang.prototype; public class Client { public static void main(String[] args) throws CloneNotSupportedException { Feeder feeder = new Feed<span style="font-size:0px; color:#ff0000;"><a href="https://www.cialisrr.com/">犀利士</a> </span>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); } }
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);
  }
}

运行结果:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
net.mosang.prototype.Panda@15db9742
net.mosang.prototype.Panda@6d06d69c
p1----->net.mosang.prototype.Panda@15db9742p1饲养员:----->张小胖
p2----->net.mosang.prototype.Panda@6d06d69cp2饲养员:----->张小胖
net.mosang.prototype.Panda@15db9742 net.mosang.prototype.Panda@6d06d69c p1----->net.mosang.prototype.Panda@15db9742p1饲养员:----->张小胖 p2----->net.mosang.prototype.Panda@6d06d69cp2饲养员:----->张小胖
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方法:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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; /** * * @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;
/**
 * 
 * @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;
  }
  }
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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 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 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();
  }
  
}

 

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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);
}
}
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); } }
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);
  }
}

运行结果:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
net.mosang.prototype.Panda@15db9742
net.mosang.prototype.Panda@6d06d69c
p1----->net.mosang.prototype.Panda@15db9742p1饲养员:----->张小胖
p2----->net.mosang.prototype.Panda@6d06d69cp2饲养员:----->张大胖
net.mosang.prototype.Panda@15db9742 net.mosang.prototype.Panda@6d06d69c p1----->net.mosang.prototype.Panda@15db9742p1饲养员:----->张小胖 p2----->net.mosang.prototype.Panda@6d06d69cp2饲养员:----->张大胖
net.mosang.prototype.Panda@15db9742
net.mosang.prototype.Panda@6d06d69c
p1----->net.mosang.prototype.Panda@15db9742p1饲养员:----->张小胖
p2----->net.mosang.prototype.Panda@6d06d69cp2饲养员:----->张大胖

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

 

 >>



© 2009-2024 MOSANG.NET DESIGNED BY HEIRY