我的编程空间,编程开发者的网络收藏夹
学习永远不晚

一文带你了解Java创建型设计模式之原型模式

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

一文带你了解Java创建型设计模式之原型模式

原型模式

概述

原型模式(Prototype Pattern)是属于创建型模式。

它指用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

原型模式的核心在于拷贝原型对象。以存在的一个对象为原型,直接基于内存二进制流进行拷贝,无需再经历耗时的对象初始化过程(不调用构造函数),性能提升许多。

当直接创建对象的代价比较大时,则采用这种模式。利用当前系统中已存在的对象作为原型,对其进行克隆,避免初始化的过程。

优缺点

优点:

1.java自带的原型模式是基于内存二进制流的拷贝,比直接new一个对象性能上提升许多

2.使用原型模式将对象复制一份并将其状态保存起来,简化创建对象的过程,以便在需要的时候使用

缺点:

1.需要为每一个类配置一个克隆方法

2克隆方法位于类的内部,当对已有类进行改造的时候,需要修改代码,违反开闭原测

3.在实现深克隆时需要编写较为复杂的代码,而且当对象之间存在多重嵌套引用时,为了实现深克隆,每一层对象对应的类都必须支特深克隆,实现比较麻烦

应用场景

1.类初始化消耗资源较多

2.new产生的一个对象需要非常繁琐的过程(数据准备或访问权限)

3.构造函数处比较复杂

4.循环体中生产大量对象时

5.资源优化场景

6.性能和安全要求的场景

主要角色

1.客户(Client)角色

客户端类向原型管理器提出创建对象的请求。

2.抽象原型(Prototype)角色

这是一个抽象角色,此角色给出所有的具体原型类所需的接口。

3.具体原型(Concrete Prototype)角色

被复制的对象。此角色需要实现抽象的原型角色所要求的接口。

4.原型管理器(Prototype Manager)角色

创建具体原型类的对象,并记录每一个被创建的对象。

原型模式的基本使用

创建原型接口

public interface IPrototype<T> {
    T clone();
}

创建具体需要克隆对象

@Data
@ToString
public class ConcretePrototype implements IPrototype {
    private int age;
    private String name;
    @Override
    public ConcretePrototype clone() {
        ConcretePrototype concretePrototype = new ConcretePrototype();
        concretePrototype.setAge(this.age);
        concretePrototype.setName(this.name);
        return concretePrototype;
    }
}

使用

    public static void main(String[] args) {
        //创建原型对象
        ConcretePrototype prototype = new ConcretePrototype();
        prototype.setAge(20);
        prototype.setName("jack");
        System.out.println(prototype);
        //拷贝原型对象
        ConcretePrototype cloneType = prototype.clone();
        System.out.println(cloneType);
    }

JDK自带原型接口的使用

原型模式就是如此简单,通常开发中不会这样使用。其实JDK提供了一个现成的API接口,那就是Cloneable接口。

@Data
@ToString
public class ConcretePrototype implements Cloneable {
    private int age;
    private String name;
    private List<String> hobbies;
    @Override
    public ConcretePrototype clone() {
        try {
            return (ConcretePrototype)super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
            return null;
        }
    }
}

浅克隆与深度克隆

浅克隆

添加一个hobby属性,当给克隆对象的hobby属性添加一项时,最终结果会导致原型对象发生变化,也就是hobby属性用于一个内存地址。这就是浅克隆。

@Data
@ToString
public class ConcretePrototype implements Cloneable {
    private int age;
    private String name;
    private List<String> hobby;
    @Override
    public ConcretePrototype clone() {
        try {
            return (ConcretePrototype)super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
            return null;
        }
    }
}
    public static void main(String[] args) {
        ConcretePrototype prototype = new ConcretePrototype();
        prototype.setAge(22);
        prototype.setName("jack");
        List<String> hobby = new ArrayList<String>();
        hobby.add("java");
        hobby.add("python");
        hobby.add("go");
        prototype.setHobby(hobby);
        // 拷贝原型对象
        ConcretePrototype cloneType = prototype.clone();
        cloneType.getHobby().add("php");
        System.out.println("原型对象:" + prototype);
        System.out.println("克隆对象:" + cloneType);
        System.out.println(prototype == cloneType);
        System.out.println(prototype.getHobby() == cloneType.getHobby());
    }

原型对象:ConcretePrototype(age=22, name=jack, hobby=[java, python, go, php])
克隆对象:ConcretePrototype(age=22, name=jack, hobby=[java, python, go, php])
false
true

深度克隆

可使用序列化方式实现对象的深度克隆

@Data
@ToString
public class ConcretePrototype implements Cloneable, Serializable {
    private int age;
    private String name;
    private List<String> hobby;
    @Override
    public ConcretePrototype clone() {
        try {
            return (ConcretePrototype) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
            return null;
        }
    }
    public ConcretePrototype deepClone() {
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(this);
            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bis);
            return (ConcretePrototype) ois.readObject();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}
    public static void main(String[] args) {
        //创建原型对象
        ConcretePrototype prototype = new ConcretePrototype();
        prototype.setAge(22);
        prototype.setName("jack");
        List<String> hobby = new ArrayList<String>();
        hobby.add("java");
        hobby.add("python");
        hobby.add("go");
        prototype.setHobby(hobby);
        // 拷贝原型对象
        ConcretePrototype cloneType = prototype.deepClone();
        cloneType.getHobby().add("php");
        System.out.println("原型对象:" + prototype);
        System.out.println("克隆对象:" + cloneType);
        System.out.println(prototype == cloneType);
        System.out.println(prototype.getHobby() == cloneType.getHobby());
    }

原型对象:ConcretePrototype(age=22, name=jack, hobby=[java, python, go])
克隆对象:ConcretePrototype(age=22, name=jack, hobby=[java, python, go, php])
false
false

也可这样操作,多克隆一次

    public ConcretePrototype deepClone2() {
        try {
            ConcretePrototype result = (ConcretePrototype) super.clone();
            result.hobby = (List) ((ArrayList) result.hobby).clone();
            return result;
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
            return null;
        }
    }

单例的破坏

如果克隆的目标对象是单例对象,深克隆就会破坏单例。

解决方案:禁止深克隆。

1.让单例类不实现Cloneable接口

2.重写clone方法,在clone方法中返回单例对象即可

@Data
@ToString
public class ConcretePrototype implements Cloneable {
    private static  ConcretePrototype instance = new ConcretePrototype();
    private ConcretePrototype(){}
    public static ConcretePrototype getInstance(){
        return instance;
    }
    @Override
    public ConcretePrototype clone() {
       return instance;
    }
}

到此这篇关于一文带你了解Java创建型设计模式之原型模式的文章就介绍到这了,更多相关Java原型模式内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

一文带你了解Java创建型设计模式之原型模式

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Java创建型设计模式之单例模式

Java单例模式是一种设计模式,它确保一个类只有一个实例,并提供一个全局访问点。可以使用多种方式实现单例模式,如饿汉式、懒汉式、双重检查锁定、静态内部类、枚举等,每种方式都有其优缺点,需要根据具体情况选择使用
2023-05-18

Java创建型设计模式之建造者模式详解

建造者模式是Java中一种创建型设计模式,它的主要目的是将一个复杂对象的构建过程分解为多个简单对象的构建过程,本文将详细介绍Java中的建造者模式,包括它的定义、结构、实现方法以及应用场景等方面,希望对大家有所帮助
2023-05-19

Java设计模式中的原型模式讲解

原型模式是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式,今天通过本文给大家介绍下Java 原型设计模式,感兴趣的朋友一起看看吧
2023-05-18

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录