设计模式——原型模式

场景:
写好多份简历

初步实现:
工作经历类:

package Prototype;

import java.io.Serializable;

public class workExperience implements Serializable {
    private String workdate;
    private String workCompany;
    public String getWorkdate() {
        return workdate;
    }
    public workExperience setWorkdate(String workdate) {
        this.workdate = workdate;
        return this;
    }
    public String getWorkCompany() {
        return workCompany;
    }
    public workExperience setWorkCompany(String workCompany) {
        this.workCompany = workCompany;
        return this;
    }
}

Resume类:

package Prototype;

import java.io.*;
import java.nio.file.Watchable;

public class Resume implements Cloneable, Serializable {
    private String name;
    private String gender;
    private int age;
    private workExperience we;
    public Resume(){
        we = new workExperience();
    }
    public void display(){
        System.out.println(this.getName()+this.getGender()+this.getAge()+this.getWorkExperience().getWorkdate()+this.getWorkExperience().getWorkCompany());
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public workExperience getWorkExperience(){
        return we;
    }

    public void setWorkExperience(String workDate,String workCompany){
        we.setWorkdate(workDate);
        we.setWorkCompany(workCompany);
    }

    public Object deepClone() throws Exception{
        // 序列化
        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();
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

客户端:

package Prototype;
public class MainTest {
    public static void main(String[] args) {
        Resume a= new Resume();
        a.setName("a");
        a.setAge(18);
        a.setGender("女");
        a.setWorkExperience("2008-2015","xx");

        Resume b = new Resume();
        b.setName("a");
        b.setAge(18);
        b.setGender("女");
        b.setWorkExperience("2008-2015","xx");
        a.display();
        b.display();
    }
}

在这里插入图片描述
但这样的客户端是很麻烦的,每次都需要实例化,如果写错一个字,每次都需要改
如果改成下面这种:在这里插入图片描述
这是在传引用,而不是传值,这样做就如同在b纸张和c纸张上写着:简历在a处一样,没有实际内容。所以应该用clone的方法

clone分为深拷贝和浅拷贝,其实现方式是通过调用Object类的clone方法来完成。在Obiect.class类中,源码为:
protected native Object clone() throws CloneNotSupportedException;

Java 将内存空间分为堆和栈。基本类型直接在栈中存储数值,而引用类型是将引用放在栈中,实际存储的值是放在堆中,通过栈中的引用指向堆中存放的数据。
在这里插入图片描述
上图定义的 a 和 b 都是基本类型,其值是直接存放在栈中的;而 c 和 d 是 String 声明的,这是一个引用类型,引用地址是存放在 栈中,然后指向堆的内存空间。
在这里插入图片描述
d = c;这条语句表示将 c 的引用赋值给 d,那么 c 和 d 将指向同一块堆内存空间。

浅拷贝:

package Clone;

import java.io.*;

public class Person implements Cloneable , Serializable {
    public String name;
    public int page;
    public Address address;

    public Person(String name, int page) {
        this.name = name;
        this.page = page;
        this.address = new Address();
    }

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

    public String getName() {
        return name;
    }

    public int getPage() {
        return page;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setPage(int page) {
        this.page = page;
    }

    public void setAddress(String provices,String city) {
        address.setAddress(provices,city);
    }

    public void display(String displayname){
        System.out.println(displayname+"name"+name+",page"+page+",address"+address);
    }

  
}

package Clone;
import java.io.Serializable;
public class Address implements Serializable {
    private String provices;
    private String city;
    public void setAddress(String provices,String city){
        this.provices = provices;
        this.city = city;
    }
    @Override
    public String toString() {
        return "Address{" +
                "provices='" + provices + '\'' +
                ", city='" + city + '\'' +
                '}';
    }
}

客户端:

package Clone;

public class shallowClone {
    public static void main(String[] args) throws Exception {
        Person p1 = new Person("yan",23);
        p1.setAddress("山西省","汾阳市");
        Person p2 =(Person) p1.clone();
        System.out.println("p1"+p1);
        System.out.println("p1.getname"+p1.getName().hashCode());
        System.out.println("p2"+p2);
        System.out.println("p2.getname"+p2.getName().hashCode());

        p1.display("p1");
        p2.display("p2");
        p2.setAddress("北京","北京");
        System.out.println("只修改p2");
        p1.display("p1");
        p2.display("p2");
    }
}

在这里插入图片描述
调用对象的 clone 方法,必须要让类实现 Cloneable 接口,并且覆写 clone 方法。
但是只修改了p2,却将p1也修改了,也就是说对象 Person 的属性 Address,经过 clone 之后,其实只是复制了其引用,他们指向的还是同一块堆内存空间,当修改其中一个对象的属性 Address,另一个也会跟着变化。

浅拷贝:创建一个新对象,然后将当前对象的非静态字段复制到该新对象,如果字段是值类型的,那么对该字段执行复制;如果该字段是引用类型的话,则复制引用但不复制引用的对象。因此,原始对象及其副本引用同一个对象。

深拷贝:
利用序列化:注意每个需要序列化的类都要实现 Serializable 接口,如果有某个属性不需要序列化,可以将其声明为 transient,即将其排除在克隆属性之外。

//深度拷贝
public Object deepClone() throws Exception{
    // 序列化
    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();
}

address类改为如下:

package Clone;

import java.io.*;

public class Person implements Cloneable , Serializable {
    public String name;
    public int page;
    public Address address;

    public Person(String name, int page) {
        this.name = name;
        this.page = page;
        this.address = new Address();
    }

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

    public String getName() {
        return name;
    }

    public int getPage() {
        return page;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setPage(int page) {
        this.page = page;
    }

    public void setAddress(String provices,String city) {
        address.setAddress(provices,city);
    }

    public void display(String displayname){
        System.out.println(displayname+"name"+name+",page"+page+",address"+address);
    }

    //深度拷贝
    public Object deepClone() throws Exception{
        // 序列化
        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();
    }
}

客户端:

package Clone;

public class Clone {
    public static void main(String[] args) throws Exception {
        Person p1 = new Person("yan",23);
        p1.setAddress("山西省","汾阳市");
        Person p2 =(Person) p1.deepClone();
        System.out.println("p1"+p1);
        System.out.println("p1.getname"+p1.getName().hashCode());
        System.out.println("p2"+p2);
        System.out.println("p2.getname"+p2.getName().hashCode());

        p1.display("p1");
        p2.display("p2");
        p2.setAddress("北京","北京");
        System.out.println("只修改p2");
        p1.display("p1");
        p2.display("p2");
    }
}

在这里插入图片描述
原型模式:
用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象
在这里插入图片描述
简历类:

package Prototype;

import java.io.*;
import java.nio.file.Watchable;

public class Resume implements Cloneable, Serializable {
    private String name;
    private String gender;
    private int age;
    private workExperience we;
    public Resume(){
        we = new workExperience();
    }
    public void display(){
        System.out.println(this.getName()+this.getGender()+this.getAge()+this.getWorkExperience().getWorkdate()+this.getWorkExperience().getWorkCompany());
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public workExperience getWorkExperience(){
        return we;
    }

    public void setWorkExperience(String workDate,String workCompany){
        we.setWorkdate(workDate);
        we.setWorkCompany(workCompany);
    }

    public Object deepClone() throws Exception{
        // 序列化
        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();
    }


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

package Prototype;

import java.io.*;
import java.nio.file.Watchable;

public class Resume implements Cloneable, Serializable {
    private String name;
    private String gender;
    private int age;
    private workExperience we;
    public Resume(){
        we = new workExperience();
    }
    public void display(){
        System.out.println(this.getName()+this.getGender()+this.getAge()+this.getWorkExperience().getWorkdate()+this.getWorkExperience().getWorkCompany());
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public workExperience getWorkExperience(){
        return we;
    }

    public void setWorkExperience(String workDate,String workCompany){
        we.setWorkdate(workDate);
        we.setWorkCompany(workCompany);
    }

    public Object deepClone() throws Exception{
        // 序列化
        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();
    }


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

工作经历类:

package Prototype;

import java.io.Serializable;

public class workExperience implements Serializable {
    private String workdate;
    private String workCompany;

    public String getWorkdate() {
        return workdate;
    }

    public workExperience setWorkdate(String workdate) {
        this.workdate = workdate;
        return this;
    }

    public String getWorkCompany() {
        return workCompany;
    }

    public workExperience setWorkCompany(String workCompany) {
        this.workCompany = workCompany;
        return this;
    }
}

客户端:

package Prototype;
public class Client {
    public static void main(String[] args) throws Exception {
        System.out.println("浅度拷贝");
        Resume r1 = new Resume();
        r1.setName("a");
        r1.setAge(25);
        r1.setGender("男");
        r1.setWorkExperience("2000-2009","xx");
        r1.display();
        Resume r2 = (Resume)r1.clone();
        System.out.println("仅修改r2");
        r2.setWorkExperience("2000-2009","YY");

        r1.display();
        r2.display();
        System.out.println("深度拷贝");
        Resume r3 = (Resume)r1.deepClone();
        r3.setWorkExperience("2018-2020","ww");
        r1.display();
        r3.display();
    }
}

在这里插入图片描述
浅拷贝:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象;
深拷贝:把引用对象的变量指向复制过的新对象,而不是原有的被引用的对象

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值