Design Pattern [4] —— 原型模式 Prototype

原型模式==》对象的克隆

优点:

  • 克隆对象会将对象已经设置的属性带出来,而不用在new之后去一个个重新设置。
  • Java 自带的原型模式基于内存二进制流的复制,在性能上比直接 new 一个对象更加优良。
  • 可以使用深克隆方式保存对象的状态,使用原型模式将对象复制一份,并将其状态保存起来,简化了创建对象的过程,以便在需要的时候使用(例如恢复到历史某一状态),可辅助实现撤销操作。

 

 看源码,clone() 前面有native修饰,本地方法,说明最终调用了C++

 


我的Github里有源码,可以clone下来自己跑下:https://github.com/Yang2199/Design-Pattern/tree/master/src

例子:

import lombok.*;
import java.util.Date;

//@Data  // Lombok的@Data注解有侵入性,会重写hashcode,导致clone对象hash值一致
@AllArgsConstructor
@Setter
@Getter
public class Video implements Cloneable{ //implements Cloneable
    private String name;
    private Date createTime;

    @Override
    public String toString() { //手动增加打印hashcode
        return  "hashCode = " + super.hashCode() +
                " Video{" +
                " name='" + name + '\'' +
                ", createTime=" + createTime +
                '}';
    }

    //Alt+Insert => Override =>clone()
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();//父类克隆
    }
}

测试:

import java.util.Date;

public class Test {
    public static void main(String[] args) throws CloneNotSupportedException, InterruptedException {
        Date date = new Date();
        Video video1 = new Video("【流浪地球】", date);
        System.out.println("video1 = " + video1);

        Video video2 = (Video) video1.clone(); //类型强制转换
        System.out.println("video2 = " + video2);

        video2.setName("【学习视频】");
System.out.println(
"video1 = " + video1); System.out.println("video2 = " + video2); } }

结果:

 

分析:

clone出来的对象的hashCode和原对象是不同的

修改属性后,两个对象就不同了,说明不是引用,而是真实复制了副本;

 


 

加入自定义类

网上说要重写自定义类的clone(),但我自己试的时候发现不用重写就ok了。。

import lombok.*;

@AllArgsConstructor
@Getter
@Setter
public class ClonePeople implements Cloneable{
    private String name;
    private Integer height;
    private Integer Intelligent;
    private BaseInfo baseInfo;//自定义类

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    @Override
    public String toString() {
        return "hashCode" + super.hashCode() +
                " ClonePeople{" +
                "name='" + name + '\'' +
                ", height=" + height +
                ", Intelligent=" + Intelligent +
                ", baseInfo=" + baseInfo +
                '}';
    }
}

 写一个自定义类:

import lombok.*;

@Setter
@Getter
@AllArgsConstructor
@ToString
public class BaseInfo {
    private String address;
    private String parents;
}

 测试:

public class Test {
    public static void main(String[] args) throws CloneNotSupportedException {
        ClonePeople clonePeople = new ClonePeople("双胞胎哥哥",195,155, new BaseInfo("地球","超人"));
                                                           //有参构造中,对象的值格式(value1 , value2) =>括号逗号

        System.out.println("OriginPeople = " + clonePeople);//这里clonePeople等价于clonePeople.toString()
//        System.out.println("clonePeople = " + clonePeople.toString());

        ClonePeople cloneLittleBrother = (ClonePeople) clonePeople.clone();//纯克隆,只有hashCode改变
        System.out.println("clone = " + cloneLittleBrother);

        //设置新属性值
        cloneLittleBrother.setName("双胞胎弟弟");
        cloneLittleBrother.setIntelligent(175);
        cloneLittleBrother.setBaseInfo(new BaseInfo("海王星","超人"));
        System.out.println("======最终结果======");
        System.out.println("cloneLittleBrother = " + cloneLittleBrother);
        System.out.println("OriginPeople = " + clonePeople.toString());
    }
}

 结果:

 

posted @ 2021-04-03 10:36  青杨风2199  阅读(101)  评论(0编辑  收藏  举报