Java23种设计模式系列——创建者模式之原型模式day2-2

181 篇文章 3 订阅
14 篇文章 0 订阅

原型模式

用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型对象相同的新对象
原型模式包含如下角色:

  1. 抽象原型类:规定了具体原型对象必须实现的的clone ()方法
  2. 具体原型类:实现抽象原型类的clone ()方法,它是可被复制的对象
  3. 访问类:使用具体原型类中的clone ()方法来复制新的对象

原型模式分类

  1. 深克隆:创建一个对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址(完全独立的一个对象,引用类型有自己的内存地址)
  2. 浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址(非完全独立,其引用类型若克隆对象修改会影响原型对象)

如何实现克隆

Object类中的clone()方法实现浅克隆
Cloneabel接口的实现标志当前类是可被克隆的

String不是基本类型但可以浅克隆

String是采用(字符串池)string pool的方式,当修改值后会把地址返回,不同的字符串其地址不相同,如果字符串池中有该字符串,会直接返回地址;如果没有,会在池中重新创建一个并返回地址。因为修改后其地址不一样,所以不会影响原来的值

浅克隆示例

  • 原型必须实现Cloneable接口
  • 重写Object类的clone方法,修改类型
  • 浅克隆的引用数据类型的修改会影响原先的原型
  • 克隆出来的对象与原型并不是一个对象(内存地址不同)

克隆原型(Man)

package builder_pattern.clone;

public class Man implements Cloneable{

    private String name;
    private int age;
    private double height;
    private Life life;

    public Man() {
        this.name = "张三";
        this.age = 29;
        this.height = 177.5D;
        this.life = new Life();
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }

    public Life getLife() {
        return life;
    }

    public void setLife(Life life) {
        this.life = life;
    }

    @Override
    public String toString() {
        return "Man{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", height=" + height +
                ", life=" + life +
                '}';
    }

    @Override
    protected Man clone() throws CloneNotSupportedException {
        System.out.println("对原型进行克隆");
        return (Man) super.clone();
    }
}

Man中的引用类型(Life)

package builder_pattern.clone;

public class Life {
    private String LifeStyle;

    public Life() {
        this.LifeStyle = "peace";
    }

    public void setLifeStyle(String lifeStyle) {
        LifeStyle = lifeStyle;
    }

    public String getLifeStyle() {
        return LifeStyle;
    }

    @Override
    public String toString() {
        return "Life{" +
                "LifeStyle='" + LifeStyle + '\'' +
                '}';
    }
}

测试类

package builder_pattern.clone;

public class CloneMachine {
    public static void main(String[] args) throws CloneNotSupportedException {
        //创建原型
        Man man = new Man();
        //进行克隆
        Man clone = man.clone();

        System.out.println(clone==man);
        System.out.println("原型:"+man.toString());
        System.out.println("克隆:"+clone.toString());
        //对克隆对象修改
        clone.setName("李四");
        clone.setAge(21);
        clone.setHeight(169.8D);
        Life life = clone.getLife();
        life.setLifeStyle("mass");
        clone.setLife(life);
        System.out.println("原型:"+man.toString());
        System.out.println("修改后的克隆:"+clone.toString());
    }
}
结果

在这里插入图片描述

深克隆(序列化方式)

通过序列化和反序列化实现

  • 原型类和引用类必须实现Serializable接口
  • 使用ByteArrayInputStream 和 ByteArrayOutputStream结合ObjectInputStream 和 ObjectOutputStream进行克隆

Man(原型类)

package builder_pattern.clone.deep;

import java.io.Serializable;

public class Man implements Serializable {

    private String name;
    private int age;
    private double height;
    private Life life;

    public Man() {
        this.name = "张三";
        this.age = 29;
        this.height = 177.5D;
        this.life = new Life();
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }

    public Life getLife() {
        return life;
    }

    public void setLife(Life life) {
        this.life = life;
    }

    @Override
    public String toString() {
        return "Man{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", height=" + height +
                ", life=" + life +
                '}';
    }


}

引用类型

package builder_pattern.clone.deep;

import java.io.Serializable;

public class Life implements Serializable {
    private String LifeStyle;

    public Life() {
        this.LifeStyle = "peace";
    }

    public void setLifeStyle(String lifeStyle) {
        LifeStyle = lifeStyle;
    }

    public String getLifeStyle() {
        return LifeStyle;
    }

    @Override
    public String toString() {
        return "Life{" +
                "LifeStyle='" + LifeStyle + '\'' +
                '}';
    }
}

测试

package builder_pattern.clone.deep;

import java.io.*;

public class CloneMachine {
    public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException {
        //创建原型
        Man man = new Man();
        //序列化
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(out);
        objectOutputStream.writeObject(man);
        //反序列化,进行克隆
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(out.toByteArray());
        ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
        Man cloneMan = (Man) objectInputStream.readObject();
        Life life = cloneMan.getLife();
        life.setLifeStyle("mass");
        cloneMan.setLife(life);
        System.out.println(man.toString());
        System.out.println(cloneMan.toString());
        System.out.println(cloneMan == man);
    }
}

结果

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值