美文网首页
原型模式

原型模式

作者: c_gentle | 来源:发表于2022-02-15 08:39 被阅读0次
原型模式简介

原型模式通过一个对象实例确定新创建对象的种类, 并拷贝创建新的实例; 总的来说, 原型模式就是从一个对象克隆出一个新的对象, 并使这个新对象具有原对象的属性和特征。
实际开发中, 可能需要在原有对象的基础上保留做备用, 并copy一个新对象进行另外分支的代码逻辑处理; 也可能需要在循环中更改原对象地址值以保留现阶段对象, 避免循环进行重复覆盖; 在这种情况下, 都需要对原有对象进行处理, 这时候就需要原型模式的辅助, 原型模式在进行对象copy时, 分为浅拷贝和深拷贝, 下面将分别分析。

浅拷贝
//引用类型对象
public class Person implements Serializable {
    private String name;
    private String gender;

    public Person(String name, String gender) {
        this.name = name;
        this.gender = gender;
    }

    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 class ShallowCopy implements Cloneable{
    private String type;
    private Person person;

    public ShallowCopy(String type, Person person) {
        this.type = type;
        this.person = person;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public Person getPerson() {
        return person;
    }

    public void setPerson(Person person) {
        this.person = person;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
//测试类
public class Test {
    public static void main(String[] args) {
        Person person=new Person("张三","男");
        ShallowCopy shallowCopy=new ShallowCopy("甜瓜",person);
        try{
            ShallowCopy copy=(ShallowCopy)shallowCopy.clone();
            System.out.println("原值地址 : " + shallowCopy);
            System.out.println("拷贝值地址 : " + copy);
            System.out.println("原值TYPE : " + shallowCopy.getType());
            System.out.println("拷贝值TYPE : " + copy.getType());
            System.out.println("原值PERSON : " + shallowCopy.getPerson());
            System.out.println("拷贝值PERSON : " + copy.getPerson());
        }catch (Exception e){


        }
    }
}

输出结果


image.png

对COPY对象属性值进行重新赋值

public class Test {
    public static void main(String[] args) {
        Person person = new Person("张三", "男");
        ShallowCopy shallowCopy = new ShallowCopy("甜瓜", person);
        try {
            ShallowCopy copy = (ShallowCopy) shallowCopy.clone();
            copy.setType("西瓜");
            copy.getPerson().setName("李四");
            copy.getPerson().setGender("女");
            System.out.println("原值地址 : " + shallowCopy);
            System.out.println("拷贝值地址 : " + copy);
            System.out.println("原值TYPE : " + shallowCopy.getType());
            System.out.println("拷贝值TYPE : " + copy.getType());
            System.out.println("原值PERSON : " + shallowCopy.getPerson());
            System.out.println("拷贝值PERSON : " + copy.getPerson());
        } catch (Exception e) {
            e.printStackTrace();

        }
    }
}

运行结果


image.png
image.png
浅拷贝总结

-- copy后原有对象和copy对象堆内存地址不同,分别为不同对象
-- copy后原有对象和copy对象所属属性对象指向相同的内存地址(实例拷贝,但所属属性没有拷贝)属性为引用类型 直接拷贝的内存地址 而不是新开辟内存地址,对copy后的属性进行修改时,影响原有对象属性
-- 实例所属属性进行传递遵循JVM规范

深拷贝

深拷贝相对与浅拷贝,不止改变了实例对象的内存地址,也改变了所属引用类型属性的内存地址。
引用类型对象类, 同上

//模型类
public class DeepCopy implements Cloneable, Serializable {
    private String type;
    private Person person;

    public DeepCopy(String type, Person person) {
        this.type = type;
        this.person = person;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public Person getPerson() {
        return person;
    }

    public void setPerson(Person person) {
        this.person = person;
    }



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

    protected Object deepCopy() {
        try {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            ObjectOutputStream stream = new ObjectOutputStream(outputStream);
            stream.writeObject(this);

            ByteArrayInputStream bis = new ByteArrayInputStream(outputStream.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bis);
            return ois.readObject();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}

这里通过IO读写操作实现对象深copy
Client测试类

  public static void main(String[] args) {
        Person person = new Person("张三", "男");
        DeepCopy deepCopy = new DeepCopy("西瓜太郎", person);
        try {
            DeepCopy copy = (DeepCopy) deepCopy.clone();

            System.out.println("原值地址 : " + deepCopy);
            System.out.println("拷贝值地址 : " + copy);
            System.out.println("原值TYPE : " + deepCopy.getType());
            System.out.println("拷贝值TYPE : " + copy.getType());
            System.out.println("原值PERSON : " + deepCopy.getPerson());
            System.out.println("拷贝值PERSON : " + copy.getPerson());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

控制台结果


image.png
image.png

对copy实例所有属性进行重新重新赋值
测试类

 public static void main(String[] args) {
        Person person = new Person("张三", "男");
        DeepCopy deepCopy = new DeepCopy("西瓜太郎", person);
        try {
            DeepCopy copy = (DeepCopy) deepCopy.clone();
            copy.setType("西瓜");
            copy.getPerson().setName("李四");
            copy.getPerson().setGender("女");
            System.out.println("原值地址 : " + deepCopy);
            System.out.println("拷贝值地址 : " + copy);
            System.out.println("原值TYPE : " + deepCopy.getType());
            System.out.println("拷贝值TYPE : " + copy.getType());
            System.out.println("原值PERSON : " + deepCopy.getPerson());
            System.out.println("拷贝值PERSON : " + copy.getPerson());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

输出结果


image.png
image.png

从控制台结果看出,所属属性地址值在copy后发生变更,对copy对象在新地址上的属性进行重新赋值,不影响原对象
深拷贝总结 :
-- 拷贝后copy对象和copy对象属性地址值与原对象完全变更
-- copy对象/原对象值变更/引用变更不互相影响

原型模式总结

浅拷贝和深拷贝都生成了一个和原有对象一样的新实例,且两个对象具有不同的地址值。但值得注意的是,浅拷贝后,实例所有引用类型属性在堆内存的地址值没有发生改变,即原有对象和copy对象的所属属性分别指向同一块堆内存,这在开发中容易产生实例内容的关联修改。深拷贝合理的规避了浅拷贝的这一不足,拷贝后对象及对象所属属性的堆内存地址值全都发生了改变,但深拷贝的拷贝逻辑不依赖JDK默认逻辑,需要根据业务逻辑重新编写clone()方法。

相关文章

  • 第3章 创建型模式-原型模式

    一、原型模式简介 二、原型模式的优点 ■ 三、原型模式的使用场景 ■ 四、原型模式的实例

  • 设计模式之原型模式(Prototype 模式)

    引入原型模式 原型模式的实例 为什么需要使用原型模式 引入原型模式 如果读者很熟悉javascript的话,对原型...

  • 初始设计模式之原型模式

    原型模式是什么? 原型模式怎么用?浅拷贝深拷贝 原型模式再理解 一、原型模式是什么? ​ 原型模式是一种创建型设计...

  • 设计模式之原型模式(创建型)

    [TOC] 模式定义 原型模式(Prototype Pattern):原型模式是提供一个原型接口,提供原型的克隆,...

  • 原型模式C++

    原型模式,用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。 原型模式结构图 原型模式基本代码 原型...

  • 设计模式:原型

    原型模式基本介绍原型模式的实现源码中的原型模式记录 原型模式基本介绍 定义:用原型实例指定创建对象的种类,并通过复...

  • js集成

    原始继承模式--原型链 2:借用构造函数 3:共享构造原型 4:圣杯模式原型链; 构造函数; 共享原型; 圣杯模式...

  • 关于JavaScript创建对象的多种方式

    JavaScript创建对象的方法 工厂模式 构造函数模式 原型模式 组合使用构造函数模式和原型模式 动态原型模式...

  • 前端面试题总结【37】:javascript对象的几种创建方式

    工厂模式 构造函数模式 原型模式 混合构造函数和原型模式 动态原型模式 寄生构造函数模式 稳妥构造函数模式 推荐:...

  • 设计模式之原型模式

    原型模式 原型模式(prototype)是指原型实例指向对象的种类,并且通过拷贝这些原型创建新的对象 模式作用: ...

网友评论

      本文标题:原型模式

      本文链接:https://www.haomeiwen.com/subject/mmzclrtx.html