设计模式之原型模式

来源:互联网 发布:怎么查看淘宝注册日期 编辑:程序博客网 时间:2024/06/05 02:54

原型模式(Prototype):用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

一、原型模式

原型模式其实就是从一个对象再创建另一个对象,而且不需要知道详细的创建细节,其UML图如下:

这里写图片描述
原型模式由以下部分组成:

客户(Client)角色:客户类提出创建对象的请求。

抽象原型(Prototype)角色:这是一个抽象角色,通常由一个Java接口或Java抽象类实现。此角色给出所有的具体原型类所需的接口clone()。

具体原型(ConcretePrototype)角色:被复制的对象。此角色需要实现抽象的原型角色所要求的接口。

二、案例分析

在《西游记》中,孙悟空,拔一根毫毛,吹一口气,就能变出成千上万的小猴子,这是孙悟空的分身术,但其实除了孙悟空,哪吒、杨戬等好多神仙都会分身术,作者在定义神仙(Prototype)原型的时候,就想好了神仙可以拥有分身术(clone()),所以,在书中,孙悟空等各路神仙都会分身,这里面就隐含了一个原型模式,其UML图如下:

这里写图片描述

代码如下:

原型类–神仙:

abstract class Prototype{   private String name;  public abstract Prototype Clone();}

具体原型类–大圣

class SunWuKong extends Prototype{  private String name;  public Prototype clone{    return (Prototype)this.MemberwiseClone();  }}

具体原型类–哪吒

class NeZha extends Prototype{  private String name;  public Prototype clone{    return (Prototype)this.MemberwiseClone();  }}

故事上演:

 public class Story{         public static void main(String[] args) {          SunWuKong suk = new SunWuKong ();          suk.setName("我是孙大圣");          System.out.println(suk.getName());          SunWuKong monkey1 = (SUnWuKong)suk.clone();           monkey1 .setName("我是小猴子1");          System.out.println(monkey1.getName());          SunWuKong monkey2 = (SUnWuKong)suk.clone();          monkey2 .setName("我是小猴子2");          System.out.println(monkey2.getName());        } }

运行结果:

我是孙大圣我是小猴子1我是小猴子2

这样孙悟空就能变出好多猴子了。

三、浅复制和深复制

接着让我们还是以神仙的分身术为例,我们规定,每个神仙不仅有名字,还得有武器,扩展上面的类,名字就是一个Sring类型,而武器有名字和重量,作为一个类,扩展如下:

原型类–神仙:

abstract class Prototype{   private String name;  private Weapon weapon;   public void  display();  public abstract Prototype Clone();}

武器类:

class Weapon(){ private String name; private String weight;}

具体原型类–大圣

class SunWuKong extends Prototype{   private String name;   private Weapon weapon;    public void  display(name,weapon){        System.out.println("我是"+this.name+",我的武器是"+weapon.name+",重量有"+weapon.weight+"。");  };  public Prototype clone{    return (Prototype)this.MemberwiseClone();  }}

故事上演:

 public class Story{         public static void main(String[] args) {        SunWuKong suk = new SunWuKong ();         suk.setName("孙悟空");        suk.setWeapon(new Weapon("如意金箍棒",“一万三千五百斤”))        SunWuKong monkey1 = (SUnWuKong)suk.clone();        monkey1 .setName("小猴子1");        monkey1 .setWeapon(new Weapon("木棒",“20斤”))        SunWuKong monkey2 = (SUnWuKong)suk.clone();        monkey2 .setName("小猴子2");        monkey2 .setWeapon(new Weapon("铁棒",“50斤”))        suk.display();        monkey1.display();        monkey2.display();        } }

运行结果如下:

我是孙悟空,我的武器是如意金箍棒,重量有一万三千五百斤。我是小猴子1,我的武器是如意金箍棒,重量有一万三千五百斤。我是小猴子2,我的武器是如意金箍棒,重量有一万三千五百斤。

这个结果不是我们想要的呀,一万三千五百斤的金箍棒早就把小猴子压死了。那为什么会出现上面的结果呢?一切是因为MemberwiseClone()这个方法:

MemberwiseClone():

创建当前对象的浅表副本,该方法用来创建一个新的对象,然后将当前对象的非静态字段复制到新对象,如果该字段是值类型的,则对该字段执行逐位复制,如果该字段是引用类型的,则复制引用但不复制引用的对象。这样的操作称之为“浅复制”。

这样看来,名字是一个String类型的,就会复制成功,而武器类,是一个引用类型的,复制的是其引用,指向了同一个对象。但我们希望出现下面的结果:

我是孙悟空,我的武器是如意金箍棒,重量有一万三千五百斤。我是小猴子1,我的武器是木棒,重量有20斤。我是小猴子2,我的武器是铁棒,重量有50斤。

那又该怎么实现呢? 孙悟空因为有了分身的方法,才可以变出很多小猴子,那我们为什么不让武器类也能够分身呢,这样岂不是就会出现我们想要的结果!

代码如下:

原型类–神仙:

abstract class Prototype{   private String name;  private Weapon weapon;   public void  display();  public abstract Prototype Clone();}

武器类:

class Weapon implements ICloneable(){  private String name;  private String weight;  public Prototype clone{    return (Prototype)this.MemberwiseClone();  }}

具体原型类–大圣

class SunWuKong extends Prototype implements ICloneable{   private String name;   private Weapon weapon;    private SunWuKong (Weapon  weapon ){    this.weapon = (Weapon)weapon.clone();   }   public void  display(name,weapon){        System.out.printLn("我是"+this.name+",我的武器是"+weapon.name+",重量有"+weapon.weight+"。");  };  public Prototype clone{    return (Prototype)this.MemberwiseClone();  }}

故事上演:

 public class Story{         public static void main(String[] args) {        SunWuKong suk = new SunWuKong ();         suk.setName("孙悟空");        suk.setWeapon(new Weapon("如意金箍棒",“一万三千五百斤”))        SunWuKong monkey1 = (SUnWuKong)suk.clone();        monkey1.setName("小猴子1");        monkey1.setWeapon(new Weapon("木棒",“20斤”))        SunWuKong monkey2 = (SUnWuKong)suk.clone();        monkey2.setName("小猴子2");        monkey2.setWeapon(new Weapon("铁棒",“50斤”))        suk.display();        monkey1.display();        monkey2.display();        } }

运行结果如下:

我是孙悟空,我的武器是如意金箍棒,重量有一万三千五百斤。我是小猴子1,我的武器是木棒,重量有20斤。我是小猴子2,我的武器是铁棒,重量有50斤

武器类和孙悟空类都实现了ICloneable接口,实现了深复制的效果。
欢迎大家评论指正,点击查看其他设计模式。

原创粉丝点击