原型模式

简介: 原型模式

原型模式简介



原型模式通过一个对象实例确定新创建对象的种类, 并拷贝创建新的实例; 总的来说, 原型模式就是从一个对象克隆出一个新的对象, 并使这个新对象具有原对象的属性和特征。

实际开发中, 可能需要在原有对象的基础上保留做备用, 并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


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


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


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


image.png

image.png


从控制台结果看出,所属属性地址值在copy后发生变更,对copy对象在新地址上的属性进行重新赋值,不影响原对象


深拷贝总结 :

-- 拷贝后copy对象和copy对象属性地址值与原对象完全变更

-- copy对象/原对象值变更/引用变更不互相影响


原型模式总结



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



相关文章
|
Ubuntu 安全 Linux
不用安装虚拟机,直接在Windows上面运行Linux Bash Shell,嗯!真香!!!
不用安装虚拟机,直接在Windows上面运行Linux Bash Shell,嗯!真香!!!
661 0
|
7月前
|
存储 缓存 人工智能
阿里云Tair KVCache:打造以缓存为中心的大模型Token超级工厂
Tair KVCache 是阿里云推出的面向大语言模型推理场景的缓存加速服务,基于分布式内存池化和分级缓存体系,解决显存墙与带宽瓶颈问题。为万亿参数模型的高效推理提供技术保障,推动 AI 算力进化与规模化应用。
|
8月前
|
JavaScript 前端开发 Docker
如何通过pm2以cluster模式多进程部署next.js(包括docker下的部署)
通过这些步骤,可以确保您的Next.js应用在多核服务器上高效运行,并且在Docker环境中实现高效的容器化管理。
821 44
|
11月前
|
机器学习/深度学习 数据采集 人工智能
深入理解SVM中的核函数及其应用
深入理解SVM中的核函数及其应用
517 83
|
10月前
|
JavaScript 前端开发 测试技术
在 golang 中执行 javascript 代码的方案详解
本文介绍了在 Golang 中执行 JavaScript 代码的四种方法:使用 `otto` 和 `goja` 嵌入式 JavaScript 引擎、通过 `os/exec` 调用 Node.js 外部进程以及使用 WebView 嵌入浏览器。每种方法都有其适用场景,如嵌入简单脚本、运行复杂 Node.js 脚本或在桌面应用中显示 Web 内容。
560 15
在 golang 中执行 javascript 代码的方案详解
|
10月前
|
存储 人工智能 数据库
Codel:AI代理工具,支持在终端、浏览器、编辑器执行复杂任务和项目
Codel是一款全自主AI代理工具,支持在终端、浏览器和编辑器中执行复杂任务和项目。它运行在沙盒化的Docker环境中,具备自主操作能力,内置浏览器和文本编辑器,所有操作记录存储于PostgreSQL数据库。Codel能够自动完成复杂任务,如创建项目结构、进行网络搜索等,适用于自动化编程、研究与开发、教育与培训以及数据科学与分析等多个领域。
279 11
Codel:AI代理工具,支持在终端、浏览器、编辑器执行复杂任务和项目
|
12月前
|
存储 编译器 C语言
【C语言】学生管理系统:完整模拟与实现(一)
【C语言】学生管理系统:完整模拟与实现
207 1
|
机器学习/深度学习 数据采集 PyTorch
构建高效 PyTorch 模型:内存管理和优化技巧
【8月更文第27天】PyTorch 是一个强大的深度学习框架,被广泛用于构建复杂的神经网络模型。然而,在处理大规模数据集或使用高性能 GPU 进行训练时,有效的内存管理对于提升模型训练效率至关重要。本文将探讨如何在 PyTorch 中有效地管理内存,并提供一些优化技巧及代码示例。
1280 1
|
Python
【Leetcode刷题Python】222. 完全二叉树的节点个数
LeetCode第222题"完全二叉树的节点个数"的Python代码实现,通过递归和深度优先遍历的方法来计算给定完全二叉树的节点总数。
123 5
|
存储 NoSQL 关系型数据库
Redis系列学习文章分享---第一篇(Redis快速入门之初始Redis--NoSql+安装redis+客户端+常用命令)
Redis系列学习文章分享---第一篇(Redis快速入门之初始Redis--NoSql+安装redis+客户端+常用命令)
257 1