【Java设计模式】——原型模式

简介: 用一个已经创建出来的实例对象作为原型,复制出一个与原型相同的新对象。(类似于 一气化三清)。原型模式中的克隆分为浅拷贝和深拷贝 浅拷贝:创建出的新对象的属性和原来对象完全相同,对于非基本类型属性,其内存地址仍指向原来对象所指向的内存地址 深拷贝:创建出的新对象属性及属性中引用的其他对象也会被克隆,不再指向原有内存地址

🏵️🏵️🏵️原型模式

🍊1.概述

用一个已经创建出来的实例对象作为原型,复制出一个与原型相同的新对象.(类似于 🤪一气化三清🤪)

使用场景:

  • 对象的创建很复杂,这时使用原型模式可以快捷的创建对象
  • 性能和安全要求比较高

🍊2.结构

  • 抽象原型类: 定义具体原型对象必须实现的clone()方法
  • 具体原型类: 实现抽象原型类的clone()方法,是能够被复制的原型类
  • 访问类: 访问具体原型类中的clone()方法来复制新的对象(测试类)

🍊3.实现

原型模式中的克隆分为浅拷贝深拷贝

浅拷贝: 创建出的新对象的属性和原来对象完全相同,对于非基本类型属性,其内存地址仍指向原来对象所指向的内存地址

深拷贝: 创建出的新对象属性及属性中引用的其他对象也会被克隆,不再指向原有内存地址

注:无论是浅拷贝还是深拷贝,都会创建出一个新对象,这个对象的内存地址与原来对象一定是不相同的!!!

类似于我们电脑上的快捷方式复制文件

🌸3.1浅拷贝

🌰1.浅拷贝实现

Java中的Object类中提供了clone()方法来实现浅拷贝。Cloneable接口是原型模式结构中的抽象原型类,而实现了Cloneable接口的子实现类就是具体的原型类。

image-20220330214737654
Cloneable接口:
image-20220330214829365

抽象原型类就是上图的Cloneable接口

具体原型类:

public class RealizeCopy implements Cloneable{
    public RealizeCopy(){
        System.out.println("具体原型对象创建完成!");
    }


    @Override
    protected RealizeCopy clone() throws CloneNotSupportedException {
        System.out.println("具体原型复制成功!");

        return (RealizeCopy) super.clone();
    }
}

访问类:

public class Client {
    public static void main(String[] args) {
        //创建一个原型类对象
        RealizeCopy realizeCopy = new RealizeCopy();

        //调用RealizeCopy类中的clone方法进行对象的拷贝
        try {
            RealizeCopy clone = realizeCopy.clone();

            //比较原型对象和拷贝出的对象
            System.out.print("原型对象 vs 拷贝出的对象:");
            System.out.println(realizeCopy== clone);

        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }

    }
}

运行结果:

image-20220330220722697

浅拷贝拷贝出的新对象和原对象相同,但是内存地址不同,相当于重新new了一个对象


🍉2.浅拷贝的问题

创建一个原型对象Study,其有一个属性是student对象

public class Study implements Cloneable{

    private Student student;

    public Student getStudent() {
        return student;
    }

    public void setStudent(Student student) {
        this.student = student;
    }
    public  void show(){
        System.out.println(student.getName()+"开始学习啦......");
    }

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

}

学生类(原型对象属性引用的对象)

public class Student {
    private String name;

    public String getName() {
        return name;
    }

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

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

访问类:

public class Client {
    public static void main(String[] args) throws CloneNotSupportedException {

        //1.创建原型对象
        Study study1 = new Study();
        //创建一个学生对象
        Student student = new Student();
        student.setName("雪月清");
        //将学生对象赋值给study1对象
        study1.setStudent(student);

        //2.拷贝study1对象
        Study study2 = study1.clone();
        study2.getStudent().setName("李华");

        //3.调用show()方法
        study1.show();
        study2.show();

    }
}

运行结果:

image-20220330222807757

震惊的发现李华原来竟是我自己!!!这就是浅拷贝的问题,只能拷贝一层,也就是原型对象本身,而原型对象所引用的对象则是指向同一内存地址,因此无论是study1对student进行修改,还是study2对student进行修改都会造成两者的student属性改变。

这就是浅拷贝的非基本类型属性,其内存地址仍指向原来对象所指向的内存地址

图解:

image-20220331102207076

🌸3.2深拷贝

创建出的新对象属性及属性中引用的其他对象也会被克隆,不再指向原有内存地址

🌰1.深拷贝的实现

使用I/O流实现深拷贝

原型类(记得实现Serializable接口)

public class Student implements Serializable {
    private String name;

    public String getName() {
        return name;
    }

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

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

原型类属性引用对象类(记得实现Serializable接口)

public class Study implements Cloneable,Serializable{

    private Student student;

    public Student getStudent() {
        return student;
    }

    public void setStudent(Student student) {
        this.student = student;
    }
    public  void show(){
        System.out.println(student.getName()+"开始学习啦......");
    }

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

}

访问类

public class Client {
    public static void main(String[] args) throws Exception {

        //1.创建原型对象
        Study study1 = new Study();
        //创建一个学生对象
        Student student = new Student();
        student.setName("雪月清");
        //将学生对象赋值给study1对象
        study1.setStudent(student);

       //创建对象输出流对象
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("d:/study.txt"));
        //写对象
        oos.writeObject(study1);
        //关闭资源
        oos.close();

        //创建对象输入流对象
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("d:/study.txt"));
        //读取对象
        Study study2 = (Study) ois.readObject();
        //释放资源
        ois.close();

       study2.getStudent().setName("李华");

       study1.show();
       study2.show();

    }
}

运行结果:

image-20220331094126399

图解:

image-20220331102555474


如果喜欢文章可以三连支持!!! 💖💖💖

相关文章
|
29天前
|
设计模式 算法 Java
Java中的设计模式:提升代码质量的秘诀
【8月更文挑战第23天】在Java开发中,设计模式是提高代码可读性、可维护性和扩展性的强有力工具。本文通过浅显易懂的语言和实际案例,探讨几种常见的设计模式及其在Java中的应用,旨在帮助开发者更好地理解并运用这些模式来优化自己的代码结构。
39 2
|
6天前
|
设计模式 Java 关系型数据库
【Java笔记+踩坑汇总】Java基础+JavaWeb+SSM+SpringBoot+SpringCloud+瑞吉外卖/谷粒商城/学成在线+设计模式+面试题汇总+性能调优/架构设计+源码解析
本文是“Java学习路线”专栏的导航文章,目标是为Java初学者和初中高级工程师提供一套完整的Java学习路线。
|
2天前
|
设计模式 Java
Java设计模式:组合模式的介绍及代码演示
组合模式是一种结构型设计模式,用于将多个对象组织成树形结构,并统一处理所有对象。例如,统计公司总人数时,可先统计各部门人数再求和。该模式包括一个通用接口、表示节点的类及其实现类。通过树形结构和节点的通用方法,组合模式使程序更易扩展和维护。
Java设计模式:组合模式的介绍及代码演示
|
6天前
|
设计模式 安全 算法
【Java面试题汇总】设计模式篇(2023版)
谈谈你对设计模式的理解、七大原则、单例模式、工厂模式、代理模式、模板模式、观察者模式、JDK中用到的设计模式、Spring中用到的设计模式
【Java面试题汇总】设计模式篇(2023版)
|
6天前
|
设计模式 Java 关系型数据库
【Java笔记+踩坑】设计模式——原型模式
对比原型模式和传统方式的实现思路、代码方案、优缺点,阐述原型模式的使用场景,以及深拷贝、浅拷贝等相关概念,并扩展原型模式在Spring源码中的应用。
【Java笔记+踩坑】设计模式——原型模式
|
22天前
|
设计模式 缓存 算法
揭秘策略模式:如何用Java设计模式轻松切换算法?
【8月更文挑战第30天】设计模式是解决软件开发中特定问题的可重用方案。其中,策略模式是一种常用的行为型模式,允许在运行时选择算法行为。它通过定义一系列可互换的算法来封装具体的实现,使算法的变化与客户端分离。例如,在电商系统中,可以通过定义 `DiscountStrategy` 接口和多种折扣策略类(如 `FidelityDiscount`、`BulkDiscount` 和 `NoDiscount`),在运行时动态切换不同的折扣逻辑。这样,`ShoppingCart` 类无需关心具体折扣计算细节,只需设置不同的策略即可实现灵活的价格计算,符合开闭原则并提高代码的可维护性和扩展性。
37 2
|
22天前
|
设计模式 Java
Java 设计模式之谜:工厂模式与抽象工厂模式究竟隐藏着怎样的神奇力量?
【8月更文挑战第30天】在Java编程中,设计模式为常见问题提供了高效解决方案。工厂模式与抽象工厂模式是常用的对象创建型设计模式,能显著提升代码的灵活性、可维护性和可扩展性。工厂模式通过定义创建对象的接口让子类决定实例化哪个类;而抽象工厂模式则进一步提供了一个创建一系列相关或相互依赖对象的接口,无需指定具体类。这种方式使得系统更易于扩展和维护。
30 1
|
22天前
|
设计模式 Java
重构你的代码:探索Java中的混合、装饰器与组合设计模式
【8月更文挑战第30天】在软件开发中,设计模式为特定问题提供了结构化的解决方案,使代码更易理解、维护及扩展。本文将介绍三种常用的 Java 设计模式:混合模式、装饰器模式与组合模式,并附有示例代码展示实际应用。混合模式允许通过继承多个接口或抽象类实现多重继承;装饰器模式可在不改变对象结构的情况下动态添加新功能;组合模式则通过树形结构表示部分-整体层次,确保客户端处理单个对象与组合对象时具有一致性。
15 1
|
1月前
|
设计模式 算法 安全
Java编程中的设计模式:提升代码的可维护性和扩展性
【8月更文挑战第19天】在软件开发的世界里,设计模式是解决常见问题的一种优雅方式。本文将深入探讨Java编程语言中常用的几种设计模式,并解释如何通过这些模式来提高代码的可维护性和扩展性。文章不涉及具体的代码实现,而是侧重于理论和实践相结合的方式,为读者提供一种思考和改善现有项目的新视角。
|
1月前
|
设计模式 Java
常用设计模式介绍~~~ Java实现 【概念+案例+代码】
文章提供了一份常用设计模式的全面介绍,包括创建型模式、结构型模式和行为型模式。每种设计模式都有详细的概念讲解、案例说明、代码实例以及运行截图。作者通过这些模式的介绍,旨在帮助读者更好地理解源码、编写更优雅的代码,并进行系统重构。同时,文章还提供了GitHub上的源码地址,方便读者直接访问和学习。
常用设计模式介绍~~~ Java实现 【概念+案例+代码】