创建型设计模式03-原型模式

这篇具有很好参考价值的文章主要介绍了创建型设计模式03-原型模式。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

🧑‍💻作者:猫十二懿

🏡账号:CSDN 、个人博客 、Github

🎊公众号:猫十二懿

原型模式

1、原型模式介绍

原型模式是一种创建型设计模式,它允许通过复制现有对象来生成新对象,而无需编写从头开始创建新对象的代码。

1.1 具体介绍

在原型模式中,我们首先创建一个原型对象,然后通过复制该对象来创建新的实例,新的对象实例不需要知道任何创建的细节,只需要知道如何复制即可得到一个与原型一模一样的新对象。这种方法比直接创建对象要快,因为在复制过程中不需要执行复杂的初始化操作。原型模式还可以减少代码重复,因为我们可以通过复制现有的对象来避免多次编写相同的创建代码。

在实现原型模式时,我们通常使用一个原型管理器来存储原型对象。这个管理器允许我们在需要时获取原型对象的副本,而不是直接创建新对象。

原型模式在许多场景中都非常有用,例如在需要创建大量相似对象的情况下。它还可以用于避免复杂的初始化操作或构造函数,并且可以使代码更加灵活和可扩展。

1.2 原型模式角色

原型模式通常包括两个角色:原型类和具体原型类。

  1. 原型类是一个抽象的类或接口,声明了用于复制自己的方法。
  2. 具体原型类是具体的实现类,在实现父类(或接口)中定义的复制方法时,需要注意实现深拷贝和浅拷贝,以确保复制出来的对象完全符合预期。

2、具体例子

2.1 违反原型模式例子

复印简历的例子,对于我们程序员来说,简历也是一个很重要的东西。

Resume

/**
 * @author Shier
 * CreateTime 2023/4/21 22:03
 * 简历类
 */
public class Resume {
    private String name;
    private String sex;
    private String age;
    private String company;
    private String workTime;

    public Resume(String name) {
        this.name = name;
    }

    /**
     * 设置个人信息
     */
    public void setPersonalInfo(String sex, String age) {
        this.sex = sex;
        this.age = age;
    }

    /**
     * 设置工作经历
     */
    public void setWorkExperience(String company, String workTime) {
        this.company = company;
        this.workTime = workTime;
    }

    /**
     * 展示简历
     */
    public void showResume() {
        System.out.println("姓名:" + this.name + "\t年龄" + this.age + "\t性别" + this.sex);
        System.out.println("工作经历:" + this.company + "\t时间:" + this.workTime);
    }
}

测试类:

/**
 * @author Shier
 * CreateTime 2023/4/21 22:08
 */
public class ResumeTest1 {
    public static void main(String[] args) {
        Resume resume1 = new Resume("Shier");
        resume1.setPersonalInfo("男", "19");
        resume1.setWorkExperience("鱼皮科技", "2023-04~05");

        Resume resume2 = new Resume("Shier");
        resume2.setPersonalInfo("男", "19");
        resume2.setWorkExperience("鱼皮科技", "2023-04~05");

        Resume resume3 = new Resume("Shier");
        resume3.setPersonalInfo("男", "19");
        resume3.setWorkExperience("鱼皮科技", "2023-04~05");

        resume1.showResume();
        resume2.showResume();
        resume3.showResume();
    }
}

最终结果显示:

创建型设计模式03-原型模式

这样就可以得到三分简历,但是你有没有想过,如果我要准备一百分呢?是不是就要去new 一百个Resume类,来创建新的对象。这样做虽然是可以,但是重复的代码也太多了吧,做重复的工作,而且消耗的内存也多。

2.2 使用原型模式改进

创建型设计模式03-原型模式

那个原型抽象类Prototype是用不着的,因为克隆实在是太常用了,所以Java提供了Cloneable接口,其中就是唯一的一个方法clone(),这样你就只需要实现这个接口就可以完成原型模式了

改进后的Resume类的UML类图如下

创建型设计模式03-原型模式

具体代码如下:

/**
 * @author Shier
 * CreateTime 2023/4/21 22:03
 * 简历类
 */
public class Resume implements Cloneable {
    private String name;
    private String sex;
    private String age;
    private String company;
    private String workTime;

    public Resume(String name) {
        this.name = name;
    }

    /**
     * 设置个人信息
     */
    public void setPersonalInfo(String sex, String age) {
        this.sex = sex;
        this.age = age;
    }

    /**
     * 设置工作经历
     */
    public void setWorkExperience(String company, String workTime) {
        this.company = company;
        this.workTime = workTime;
    }

    /**
     * 展示简历
     */
    public void showResume() {
        System.out.println("姓名:" + this.name + "\t年龄" + this.age + "\t性别" + this.sex);
        System.out.println("工作经历:" + this.company + "\t时间:" + this.workTime);
    }

    /**
     * 实现clone方法
     */
    public Resume clone() {
        Resume object = null;
        // 使用克隆对象进行克隆内容
        try {
            object = (Resume) super.clone();
        } catch (CloneNotSupportedException e) {
            System.out.println("克隆异常了");
            throw new RuntimeException(e);
        }
        return object;
    }
}

测试类:

/**
 * @author Shier
 * CreateTime 2023/4/21 22:08
 */
public class ResumeTest1 {
    public static void main(String[] args) {
        Resume resume1 = new Resume("Shier");
        resume1.setPersonalInfo("男", "19");
        resume1.setWorkExperience("鱼皮科技1", "2023-04~05");
        // 使用resume1进行调用clone对象
        Resume resume2 = resume1.clone();
        resume2.setWorkExperience("鱼皮科技2", "2023-04~05");

        Resume resume3 = resume1.clone();
        resume3.setWorkExperience("鱼皮科技3", "2023-04~05");

        resume1.showResume();
        resume2.showResume();
        resume3.showResume();
    }
}

结果同上

3 浅拷贝与深拷贝

现在’简历’对象里的数据都是String型的,而String是一种拥有值类型特点的特殊引用类型,super.clone()方法是这样,如果字段是值类型的,则对该字段执行逐位复制,如果字段是引用类型,则复制引用但不复制引用的对象;因此,原始对象及其副本引用同一对象。什么意思呢?就是说如果你的’简历’类当中有对象引用,那么引用的对象数据是不会被克隆过来的。

浅拷贝:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用都仍然指向原来的对象。但我们可能更需要这样的一种需求,把要复制的对象所引用的对象都复制一遍

3.1 浅拷贝例子

/**
 * @author Shier
 * CreateTime 2023/4/21 22:32
 * 工作经历类
 */
public class WorkExperience {
    private String company;
    private String workTime;

    public String getCompany() {
        return company;
    }

    public void setCompany(String company) {
        this.company = company;
    }

    public String getWorkTime() {
        return workTime;
    }

    public void setWorkTime(String workTime) {
        this.workTime = workTime;
    }
}
/**
 * @author Shier
 * CreateTime 2023/4/21 22:03
 * 简历类
 */
public class Resume implements Cloneable {
    private String name;
    private String sex;
    private String age;

    private WorkExperience workExperience;

    public Resume(String name) {
        this.name = name;
        this.workExperience = new WorkExperience();
    }

    /**
     * 设置个人信息
     */
    public void setPersonalInfo(String sex, String age) {
        this.sex = sex;
        this.age = age;
    }

    /**
     * 设置工作经历
     */
    public void setWorkExperience(String company, String workTime) {
        this.workExperience.setCompany(company);
        this.workExperience.setWorkTime(workTime);
    }

    /**
     * 展示简历
     */
    public void showResume() {
        System.out.println("姓名:" + this.name + "\t年龄" + this.age + "\t性别" + this.sex);
        System.out.println("工作经历:" + this.workExperience.getCompany() + "\t时间:" + this.workExperience.getWorkTime());
    }

    /**
     * 实现clone方法
     */
    public Resume clone() {
        Resume object = null;
        // 使用克隆对象进行克隆内容
        try {
            object = (Resume) super.clone();
        } catch (CloneNotSupportedException e) {
            System.out.println("克隆异常了");
            throw new RuntimeException(e);
        }
        return object;
    }
}

测试类:

/**
 * @author Shier
 * CreateTime 2023/4/21 22:08
 */
public class ResumeTest1 {
    public static void main(String[] args) {
        Resume resume1 = new Resume("Shier");
        resume1.setPersonalInfo("男", "19");
        resume1.setWorkExperience("鱼皮科技1", "2023-04~05");

        Resume resume2 = resume1.clone();
        resume2.setWorkExperience("鱼皮科技2", "2023-04~05");

        Resume resume3 = resume1.clone();
        resume3.setWorkExperience("鱼皮科技3", "2023-04~05");

        resume1.showResume();
        resume2.showResume();
        resume3.showResume();
    }
}

结果显示:

创建型设计模式03-原型模式

这个结果和我们的预期的不一样,第三个把前面两个都覆盖掉了。

由于它是浅表拷贝,所以对于值类型,没什么问题,对引用类型,就只是复制了引用,对引用的对象还是指向了原来的对象,所以就会出现我给resume1、resume2、resume3三个引用设置’工作经历’,但却同时看到三个引用都是最后一次设置,因为三个引用都指向了同一个对象。

3.2 深拷贝例子

3.2.1 深拷贝介绍

深拷贝把引用对象的变量指向复制过的新对象,而不是原有的被引用的对象。

深拷贝是指创建一个新对象,并将原始对象中的所有非静态字段及其关联对象的值复制到新对象中。如果字段是基本数据类型,则拷贝它们的值;如果字段是引用类型,则递归地拷贝它们所指向的对象,直到所有引用对象都被拷贝为止。因此,原始对象和副本对象将不共享任何对象。

3.2.2 改进程序

再次修改上面的程序,UML类图如下:

创建型设计模式03-原型模式

修改工作经历类:

package com.shier.sourcepattern;

/**
 * @author Shier
 * CreateTime 2023/4/21 22:32
 * 工作经历类
 */
public class WorkExperience implements Cloneable{
    private String company;
    private String workTime;

    public String getCompany() {
        return company;
    }

    public void setCompany(String company) {
        this.company = company;
    }

    public String getWorkTime() {
        return workTime;
    }

    public void setWorkTime(String workTime) {
        this.workTime = workTime;
    }
    /**
     * 实现clone方法
     */
    public WorkExperience clone() {
        WorkExperience object = null;
        // 使用克隆对象进行克隆内容
        try {
            object = (WorkExperience) super.clone();
        } catch (CloneNotSupportedException e) {
            System.out.println("克隆异常了");
            throw new RuntimeException(e);
        }
        return object;
    }
}

修改简历类:

/**
 * 实现clone方法
 */
public Resume clone() {
    Resume object = null;
    // 使用克隆对象进行克隆内容
    try {
        object = (Resume) super.clone();
        // 进行深拷贝
        this.workExperience = this.workExperience.clone();
    } catch (CloneNotSupportedException e) {
        System.out.println("克隆异常了");
        throw new RuntimeException(e);
    }
    return object;
}

测试的代码不用改变

运行结果显示:

创建型设计模式03-原型模式

看到这个三个都是不同的,即达到了目的。

4、总结

原型模式通过使用原型管理器来存储原型对象,并在需要时获取原型对象的副本,以避免多次创建相同的对象。

原型模式优点:

  1. 可以在不编写创建代码的情况下创建新对象。
  2. 可以减少代码重复,因为我们可以通过拷贝现有对象来避免多次编写相同的创建代码。
  3. 可以减少初始化操作或构造函数,并使代码更加灵活和可扩展。

原型模式缺点:

  1. 如果拷贝操作很复杂,可能会导致性能问题。
  2. 如果对象有循环依赖关系,则需要特殊处理。

原型模式应用场景:

  1. 创建成本较大的对象:某些对象的创建过程需要耗费大量时间和资源,例如数据库连接对象、网络连接对象等。在这种情况下,使用原型模式可以避免重复创建相同的对象,从而提高系统的性能和效率。
  2. 大量相似对象的创建:某些对象可能存在大量相似的情况,例如在图形界面中创建图形对象时,往往会存在大量相似的图形对象,只是具体属性不同。在这种情况下,使用原型模式可以通过复制现有对象来创建新对象,避免从头开始创建新对象的代码。
  3. 对象的复杂组合:某些对象的创建需要组合多个对象,例如在设计图形界面中的窗口对象时,需要组合多个控件对象。在这种情况下,使用原型模式可以通过复制现有对象来创建新对象,并在需要的时候修改其中某些组件,从而简化对象的创建过程。

4.2 深浅拷贝

浅拷贝的优点:

  1. 相对于深拷贝,浅拷贝的效率更高,因为它只是拷贝引用,而不是递归地拷贝所有相关对象。
  2. 浅拷贝对于某些对象来说是合适的,例如拷贝一些不包含引用类型字段的简单对象。

浅拷贝的缺点:

  1. 如果原始对象中的引用类型字段被修改了,那么拷贝后的对象也会被修改,这可能会导致意外的副作用。

深拷贝的优点:

  1. 深拷贝可以创建完全独立的对象,与原始对象不共享任何引用对象。
  2. 深拷贝可以避免意外的副作用。

深拷贝的缺点:文章来源地址https://www.toymoban.com/news/detail-463444.html

  1. 相对于浅拷贝,深拷贝的效率更低,因为它需要递归地拷贝所有相关对象。
  2. 深拷贝可能会导致循环引用问题,需要特殊处理。

建新对象的代码。
3. 对象的复杂组合:某些对象的创建需要组合多个对象,例如在设计图形界面中的窗口对象时,需要组合多个控件对象。在这种情况下,使用原型模式可以通过复制现有对象来创建新对象,并在需要的时候修改其中某些组件,从而简化对象的创建过程。

4.2 深浅拷贝

浅拷贝的优点:

  1. 相对于深拷贝,浅拷贝的效率更高,因为它只是拷贝引用,而不是递归地拷贝所有相关对象。
  2. 浅拷贝对于某些对象来说是合适的,例如拷贝一些不包含引用类型字段的简单对象。

浅拷贝的缺点:

  1. 如果原始对象中的引用类型字段被修改了,那么拷贝后的对象也会被修改,这可能会导致意外的副作用。

深拷贝的优点:

  1. 深拷贝可以创建完全独立的对象,与原始对象不共享任何引用对象。
  2. 深拷贝可以避免意外的副作用。

深拷贝的缺点:

  1. 相对于浅拷贝,深拷贝的效率更低,因为它需要递归地拷贝所有相关对象。
  2. 深拷贝可能会导致循环引用问题,需要特殊处理。

到了这里,关于创建型设计模式03-原型模式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【设计模式】第6节:创建型模式之“原型模式”

    由于本人现在所使用的语言主要是golang,所以后面的代码主要使用golang编写。语言实现应该不是障碍,主要是理解每种设计模式它的思想。 如果对象的创建成本比较大,而同一个类的不同对象之间差别不大(大部分字段都相同),在这种情况下,我们可以利用对已有对象(原

    2024年02月06日
    浏览(49)
  • 创建型设计模式:5、原型模式(Prototype Pattern)

    目录 1、原型模式的含义 2、C++实现原型模式的简单实例 1、原型模式的含义 通过复制现有对象来创建新对象,而无需依赖于显式的构造函数或工厂方法,同时又能保证性能。 The prototype pattern is a creational design pattern in software development. It is used when the type of objects to create is det

    2024年02月13日
    浏览(43)
  • 【C++设计模式之原型模式:创建型】分析及示例

    简介 原型模式(Prototype Pattern)是一种创建型设计模式,它允许通过复制已有对象来生成新的对象,而无需再次使用构造函数。 描述 原型模式通过复制现有对象来创建新的对象,而无需显式地调用构造函数或暴露对象的创建细节。它使用原型接口来声明克隆方法,所有实现

    2024年02月07日
    浏览(39)
  • 《golang设计模式》第一部分·创建型模式-02-原型模式(Prototype)

    用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象 Prototype(抽象原型类):它是声明克隆方法的接口,或所有具体原型类的公共父类 它可以是抽象类也可以是接口,甚至还可以是具体实现类。 ConcretePrototype(具体原型类):它实现在抽象原型类中声明的

    2024年02月14日
    浏览(40)
  • Java设计模式之创建型-原型模式(UML类图+案例分析)

    目录 一、基础概念 二、UML类图 三、角色设计 四、案例分析  4.1、通用实现(浅克隆) 4.2、深克隆 五、总结 原型模式通过复制已有对象作为原型,通过复制该原型来返回一个新对象,而不是新建对象,说白了就是不断复制相同的对象罢了。 角色 描述 抽象原型类 规定了具

    2024年02月15日
    浏览(50)
  • 【java设计模式】创建型模式介绍(工厂模式、抽象工厂模式、单例模式、建造者模式、原型模式)

    简介 本文介绍Java设计模式中创建型模式的五种 一、工厂模式 工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 工厂模式提供了一种将对象的实例化过程封装在工厂类中的方式。通过使用工

    2024年02月16日
    浏览(47)
  • [设计模式Java实现附plantuml源码~创建型] 对象的克隆~原型模式

    前言: 为什么之前写过Golang 版的设计模式,还在重新写 Java 版? 答:因为对于我而言,当然也希望对正在学习的大伙有帮助。Java作为一门纯面向对象的语言,更适合用于学习设计模式。 为什么类图要附上uml 因为很多人学习有做笔记的习惯,如果单纯的只是放一张图片,那

    2024年01月23日
    浏览(42)
  • 二十三种设计模式全面解析-原型模式进阶之原型管理器:集中管理对象原型的设计模式之道

    在软件开发中,我们经常需要创建和复制对象。然而,有时候直接创建对象可能会导致性能下降或代码重复。为了解决这些问题,原型模式应运而生。而使用原型管理器(Prototype Manager)来集中管理原型对象可以进一步提高灵活性和可维护性。本文将详细介绍原型管理器的用

    2024年02月07日
    浏览(57)
  • JAVA设计模式----原型设计模式

    定义 :用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。 类型 :创建类模式 类图 : 原型模式主要用于对象的复制,它的核心是就是类图中的原型类Prototype。Prototype类需要具备以下两个条件: 实现Cloneable接口。在java语言有一个Cloneable接口,它的作用只

    2024年02月13日
    浏览(51)
  • 设计模式三(原型模式)

    在开发过程中,创建多个数据相同的对象,每次new都开销比较大,在这里可以使用对象克隆,以先创建的原型对象为模板进行对象的复制。这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。例如,一个对象

    2024年01月25日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包