2025年3月21日 星期五 甲辰(龙)年 月廿 设为首页 加入收藏
rss
您当前的位置:首页 > 计算机 > 编程开发 > 设计模式

【设计模式】10.创建型模式-原型模式(Prototype)

时间:02-01来源:作者:点击数:46

一、描述:

  将一个对象作为原型,通过对其进行复制而克隆出多个和原型类似的新实例。

二、特点:

  用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。原型实例指定了要创建的对象的种类。用这种方式创建对象非常高效,根本无须知道对象创建的细节。

三、优点:

  (1)Java自带的原型模式基于内存二进制流的复制,在性能上比直接new一个对象更加优秀。

  (2)可以使用深克隆方式保存对象的状态,使用原型模式将对象复制一份,并将其状态保存起来,简化了创建对象的过程,以便在需要的时候使用(例如恢复到历史某一状态),可辅助实现撤销操作。

四、应用:

  Object的clone方法,实体类实现Cloneable接口类,重写clone()方法,clone方法有浅拷贝和深拷贝两种:

  (1)浅拷贝:只拷贝当前主类的对象,建立一个新的复制对象,但是新的复制对象中的子对象依旧引用之前的主类的子对象地址。(注意:测试clone方法的结果,不能用@Data注解,因为@Data注解重写了hashCode方法,相同属性相同值的情况下,hashCode值一致。)

  • public class User implements Cloneable {
  • private String name;
  • private String sex;
  • private Integer age;
  • private School school;
  • public String getName() {
  • return name;
  • }
  • public void setName(String name) {
  • this.name = name;
  • }
  • public String getSex() {
  • return sex;
  • }
  • public void setSex(String sex) {
  • this.sex = sex;
  • }
  • public Integer getAge() {
  • return age;
  • }
  • public void setAge(Integer age) {
  • this.age = age;
  • }
  • public School getSchool() {
  • return school;
  • }
  • public void setSchool(School school) {
  • this.school = school;
  • }
  • @Override
  • protected User clone() throws CloneNotSupportedException {
  • return (User) super.clone();
  • }
  • public static class School implements Cloneable {
  • private String name;
  • public String getName() {
  • return name;
  • }
  • public void setName(String name) {
  • this.name = name;
  • }
  • @Override
  • protected Object clone() throws CloneNotSupportedException {
  • return super.clone();
  • }
  • }
  • }

  测试:

  • @Slf4j
  • public class MainTest {
  • public static void main(String[] args) throws CloneNotSupportedException {
  • User user = new User();
  • user.setName("张三");
  • user.setAge(18);
  • User.School school = new User.School();
  • school.setName("华师小学");
  • user.setSchool(school);
  • User user2 = user.clone();
  • log.info("user:{}",JSON.toJSONString(user));
  • log.info("user2:{}",JSON.toJSONString(user2));
  • log.info("user-hashCode:{},user2-hashCode:{},isEquals:{}", user.hashCode(), user2.hashCode(), user.hashCode() == user2.hashCode());
  • log.info("user-school-hashCode:{},user2-school-hashCode:{}, isEquals:{}", user.getSchool().hashCode(), user2.getSchool().hashCode(), user.getSchool().hashCode() == user2.getSchool().hashCode());
  • }
  • }

  运行结果:

user:{"age":18,"name":"张三","school":{"name":"华师小学"}}

user2:{"age":18,"name":"张三","school":{"name":"华师小学"}}

user-hashCode:662736689,user2-hashCode:1320677379,isEquals:false

user-school-hashCode:852687460,user2-school-hashCode:852687460, isEquals:true

  从结果可以看出来,主对象在克隆之后,hashCode值变化,说明为克隆主对象又重新开辟了内存存储。但是克隆子对象school的hashCode值仍然为原来的hashCode,说明克隆后的user2对象中的school仍然引用的user的school对象地址。这就是浅拷贝。

  浅拷贝的util方法有:

  • BeanUtil.copyProperties(user, user2);

  (2)深拷贝:比浅拷贝更进一步,子对象也都重新开辟了新的内存存储,重写clone方法:

  • /**
  • * User
  • *
  • * @author zhouxy
  • * @date 2022/5/24
  • **/
  • public class User implements Cloneable {
  • private String name;
  • private String sex;
  • private Integer age;
  • private School school;
  • //getter、setter方法
  •   ......
  • @Override
  • protected User clone() throws CloneNotSupportedException {
  • User copyUser = (User) super.clone();
  •     //重写school的clone方法
  • School school = copyUser.getSchool().clone();
  • copyUser.setSchool(school);
  • return copyUser;
  • }
  • public static class School implements Cloneable {
  • private String name;
  •      //getter、setter方法
  • .....
  • @Override
  • protected School clone() throws CloneNotSupportedException {
  • return (School) super.clone();
  • }
  • }
  • }

  测试代码仍然和浅拷贝的测试代码一致,直接显示测试结果:

  • user:{"age":18,"name":"张三","school":{"name":"华师小学"}}
  • user2:{"age":18,"name":"张三","school":{"name":"华师小学"}}
  • user-hashCode:662736689,user2-hashCode:1320677379,isEquals:false
  • user-school-hashCode:852687460,user2-school-hashCode:246399377, isEquals:false

  school的对象的hashCode也发生了变化。

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门