设计模式-原型模式

设计模式-原型模式

原型模式是什么?

原型模式是一种创建型设计模式,Prototype模式允许一个对象再创建另外一个可定制的对象,根本无需知道任何如何创建的细节,工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建。

通俗的说就是将某一事物当作原型拷贝(克隆)一份,创建一个副本。
第一只克隆羊-多莉
第一只克隆羊-多莉

用途

用于再次创建相同的复杂对象,提升效率

实现

1、通过克隆实现

/*
1、实现一个接口 Cloneable
2、重写一个方法 clone()
*/
@Data
public class Vlog implements cloneable{
  private String name;
  private Date createTime;
  
  protected Object clone() throws CloneNotSupportedException{
    return super.clone();
  }
}

客户端进行原型克隆

public class XiaoWei{
  public static void main (String[] args){
  Date date = new Date();
  Vlog v1 = new Vlog("小微的博客", date);
  Vlog v2 = (Vlog)v1.clone();
  /* 
   v1 == v2???
   这里是深克隆还是浅克隆??
  */
  date.setTime(1232432);
  /* 
   v1 == v2???
  */
  }
}

答案是:这里是浅克隆!!
深克隆、浅克隆

那么如何实现深克隆??
改造克隆方法!!

public class Vlog implements cloneable{
  private String name;
  private Date createTime;
  
  protected Object clone() throws CloneNotSupportedException{
    Object obj = super.clone();
    Vlog v = (Vlog)obj;
    //把当前这个对象的属性也克隆~
    v.createTime = (Date)this.createTime.clone();
    return obj;
  }
}

2、通过序列化、反序列化实现

较为复杂,涉及IO

@Data
public class Monkey implements Cloneable, Serializable{
  private int height;
  private int weight;
  private Date birth;
  public Monkey (){
    this.birth = new Date();
  }
  public Object deepClone() throws IOException, ClassNotFoundException{
  //将对象写到流里
  ByteArrayOutputStream bos = new ByteArrayOutputStream();
  ObjectOutputStream oos = new ObjectOutputStream(bos);
  oos.writeObject(this);
  //从流中读出来
  ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
  ObjectInputStream ois = new ObjectInputStream(bis);
  return ois.readObject();
  }
}

public class theMonkeyKing{
  public static void main(String[] args){
    Monkey monkeyKing = new Mongkey();
    Monkey copyMonkeyKing = (Monkey)monkeyKing.deepClone();
    System.out.println("俩美猴王是一个对象吗?" + (monkeyKing == copyMonkeyKing));
}

优势&&缺点

优势:

  1. 程序运行效率:可以节省new创建对象的时间,
  2. 代码开发效率:可以一个clone()方法搞定,无需复杂的赋值操作
  3. 代码的稳定性:依次一个一个的进行代码赋值,会不会因为一个Cv操作失误导致一个细微难察觉的代码bug发布出来了呢?

缺点:
原型模式最主要的缺点是每一个类都必须配备一个克隆方法。配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类来说不是很难,而对于已经有的类可能就会很麻烦,因为要修改原先的代码,还要考虑对象的结构改造。违背了“开闭原则”!!

不使用clone,怎么快速友好,非侵入的实现原型模式

org.springframework.beans.BeanUtils
org.apache.commons.beanutils.BeanUtils
相信大家都用过BeanUtils.copyProperties(),用于对象的拷贝,这里其实就是原型模式的一个应用!!
值得说明的是: spring 与apache的BeanUtils相比,在性能上spring有极大的优势,因此在简单做属性赋值的时候推荐使用spring的,经过测试在大规模的赋值操作中spring性能可以达到apace性能的100倍。

应用场景

  1. 资源优化场景。类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等。
  2. 性能和安全要求的场景。 通过 new 产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。
  3. 一个对象多个修改者的场景。一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用。
  4. 在实际项目中,原型模式很少单独出现,一般是和工厂方法模式一起出现,通过 clone 的方法创建一个对象,然后由工厂方法提供给调用者。原型模式已经与 Java 融为浑然一体,大家可以随手拿来使用。
  5. 细胞分裂。 JAVA中的 Object clone() 方法。在Spring中,用户也可以采用原型模式来创建新的bean实例,从而实现每次获取的是通过克隆生成的新实例,对其进行修改时对原有实例对象不造成任何影响。
  6. 原型模式应用于很多软件中,如果每次创建一个对象要花大量时间,原型模式是最好的解决方案。很多软件提供的复制(Ctrl + C)和粘贴(Ctrl + V)操作就是原型模式的应用,复制得到的对象与原型对象是两个类型相同但内存地址不同的对象,通过原型模式可以大大提高对象的创建效率。
  7. 在Struts2中为了保证线程的安全性,Action对象的创建使用了原型模式,访问一个已经存在的`Action对象时将通过克隆的方式创建出一个新的对象,从而保证其中定义的变量无须进行加锁实现同步,每一个Action中都有自己的成员变量,避免Struts1因使用单例模式而导致的并发和同步问题。

应用举例

  • Spring Bean 的创建,引用了单例模式+原型模式
  • 西游记里面孙悟空用猴毛变出超多个自己
  • 游戏里面的小兵和一些相似的环境布景
  • 可口可乐公司生产可乐,应用工厂模式+原型模式
  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值