软件设计模式之原型模式

一.定义

原型模式(Prototype Pattern)的简单程度仅次于单例模式和迭代器模式。正是由于简单,使用的场景才非常地多,其定义如下:
Specify the kinds of objects to create using a prototypical instance, and create new objects by copyingthis prototype.(用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。)

实际的类图模板如下:
在这里插入图片描述
原型模式的通用源码如下:
在这里插入图片描述

实现一个接口,然后重写clone方法,就完成了原型模式!

二.例子

用一个个性化服务账单,来说明什么是原型模式,看一则小故事.
现在电子账单越来越流行了,比如你的信用卡,每到月初的时候银行就会发–份电子邮件给你,说你这个月消费了多少,什么时候消费的,积分是多少等,这是每个月发一次。还有一种也是银行发的邮件你肯定非常有印象:广告信,现在各大银行的信用卡部门都在拉拢客户,电子邮件是一种廉价、快捷的通信方式,你用纸质的广告信那个费用多高呀,比如我行今天推出一个信用卡刷卡抽奖活动,通过电子账单系统可以一个晚上发送给600万客户,为什么要用电子账单系统呢?直接找个发垃圾邮件的工具不就解决问题了吗?是个好主意,但是这个方案在金融行业是行不通的,为什么?因为银行发送该类邮件是有要求的:

  • 个性化服务
    一般银行都要求个性化服务,发过去的邮件上总有一些个人信息吧,比如“XX先生”,“XX女士”等。
  • 递送成功率
    邮件的递送成功率有一定的要求,由于大批量地发送邮件会被接收方邮件服务器误认是垃圾邮件,因此在邮件头要增加一些伪造数据,以规避被反垃圾邮件引擎误认为是垃圾邮件。

从这两方面考虑广告信的发送也是电子账单系统(电子账单系统一般包括:账单分析、账单生成器、广告信管理、发送队列管理、发送机、退信处理、报表管理等)的一个子功能,我们今天就来考虑一下广告信这个模块是怎么开发的。那既然是广告信,肯定需要一个模版,然后再从数据库中把客户的信息一个一个地取出,放到模板中生成一份完整的邮件,然后扔给发送机进行发送处理,类图如图所示
在这里插入图片描述
广告模板代码
在这里插入图片描述
邮件类代码
在这里插入图片描述
在这里插入图片描述
Mail类就是一个业务对象,虽然比较长,还是比较简单的。我们再来看业务场景类是如何对邮件继续处理的,代码如下:
在这里插入图片描述
在这里插入图片描述

由于是随机数,每次运行都有所差异,不管怎么样,我们这个电子账单发送程序是编写出来了,也能正常发送。我们再来仔细地想想,这个程序是否有问题?Look here,这是一个线程在运行,也就是你发送的是单线程的,那按照一封邮件发出去需要0.02秒(够小了,你还要到数据库中取数据呢),600万封邮件需要33个小时,也就是一个整天都发送不完,今天的不发送完,明天的账单又产生了,日积月累,激起甲方人员一堆抱怨,那怎么办?
好办,把sendMail修改为多线程,但是只把sendMail修改为多线程还是有问题的呀,产生第一封邮件对象,放到线程1中运行,还没有发送出去,线程2也启动了,直接就把邮件对象mail的收件人地址和称谓修改掉了,线程不安全了。说到这里,你会说这有N多种解决办法,其中一种是使用一种新型模式来解决这个问题:通过对象的复制功能来解决这个问题,类图稍作修改,如图所示
在这里插入图片描述

修改后的邮件类
在这里插入图片描述
在这里插入图片描述
修改后的场景类
在这里插入图片描述

运行结果不变,一样完成了电子广告信的发送功能,而且sendMail即使是多线程也没有关系。注意,看Client类中的粗体字mail.clone()这个方法,把对象复制一份,产生一个新的对象,和原有对象一样,然后再修改细节的数据,如设置称谓、设置收件人地址等。这种不通过new关键字来产生一个对象,而是通过对象复制来实现的模式就叫做原型模式。

三.结论

优点

  • 性能优良
    原型模式是在内存二进制流的拷贝,要比直接new一个对象性能好很多,特别是要在一个循环体内产生大量的对象时,原型模式可以更好地体现其优点。
  • 逃避构造函数的约束
    这既是它的优点也是缺点,直接在内存中拷贝,构造函数是不会执行的,优点就是减少了约束,缺点也是减少了约束,需要大家在实际应用时考虑。

使用场景

  • 资源优化场景
    类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等。
  • 性能和安全要求的场景
    通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。
  • 一个对象多个修改者的场景
    一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用。

在实际项目中,原型模式很少单独出现,一般是和工厂方法模式一起出现,通过clone的方法创建一个对象,然后由工厂方法提供给调用者。原型模式已经与Java融为一体,大家可以随手拿来使用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/30754.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

第七章 测试

文章目录 第七章 测试7.1 编码7.1.1 选择程序设计语言1. 计算机程序设计语言基本上可以分为汇编语言和高级语言2. 从应用特点看,高级语言可分为基础语言、结构化语言、专用语言 7.1.2 编码风格 7.2 软件测试基础7.2.1 软件测试的目标7.2.2 软件测试准则7.2.3 测试方…

边缘智能:边缘计算驱动实时深度学习

边缘智能 作为人工智能领域的当红炸子鸡,深度学习技术近年来得到了学术界与产业界的大力追捧。目前,深度学习技术已在计算机视觉、自然语言处理以及语音识别等领域大放异彩,相关产品正如雨后春笋般涌现。由于深度学习模型需要进行大量的计算…

Delta 一个新的 git diff 对比显示工具

目录 介绍git diff 介绍delta介绍 一、安装1.下载 Git2.下载 delta3.解压4.修改配置文件5. 修改主题6.其他配置和说明 二、对比命令1.在项目中 git diff 常用命令2.对比电脑上两个文件3.对比电脑上的两个文件夹 三、在Git 命令行中使用效果四、在idea 的Terminal命令行中使用效…

linux 内核版本和发行版本

当要明确自己的Linux系统的版本号时,大多数情况是用命令确定Linux内核版本的。不过这个还是要与CentOS的版本号(就是你使用的Linux系统的发行版本)区分开来,这两个不是一个东西。 一、发行版本号 比如当时安装CentOS时&#x…

MySQL是什么,如何整合SpringBoot,以及使用优势

目录 一、MySQL是什么 二、如何整合SpringBoot 三、MySQL使用优势 一、MySQL是什么 MySQL是一种开源的关系型数据库管理系统,采用客户机/服务器模式实现数据存储和管理。其最初由瑞典的MySQL AB公司开发,后来被Sun Microsystems收购,最终…

【Python 随练】寻找完数

题目: 一个数如果恰好等于它的因子之和,这个数就称为"完数"。例如 61+2+3.编程找出 1000 以内的所有完数。 简介: 在本篇博客中,我们将解决一个数学问题:如何找出 1000 以内的所有…

AI绘画基于 Kaggle 10 分钟搭建 Stable Diffusion(保姆级教程)

AI绘画基于 Kaggle 10 分钟搭建 Stable Diffusion(保姆级教程) 一、引言二、安装教程1. 注册 Kaggle2. Edit My Copy3. 进行手机号的验证4. 打开 “internet off” 开关,并选择显卡5. 开启 session,运行脚本 三、主界面介绍四、注…

Windows提示“找不到rgss202j.dll”怎么办?

Rgss202j.dll文件是Windows操作系统最重要的系统文件之一,它包含了一组程序和驱动函数。如果此文件丢失或损坏,驱动程序将无法正常工作,并且相应的应用程序也将无法正常启动且运行。通常情况下,造成Rgss202j.dll文件无法找到的原因…

计算机的工作过程和主要性能指标

一、计算机的工作过程 为使计算机按预定要求工作,首先要编制程序。 程序是一个特定的指令序列,它告诉计算机要做哪些事,按什么步骤去做。 指令是一组二进制信息的代码,用来表示计算机所能完成的基本操作。 编制好的程序放在主存中…

redis 的基本介绍以及 五种 数据类型

一、redis是什么? 一句话:redis 是一个开源的、使用C语言编写的、支持网络交互,基于内存也可持久化的 key-value (非关系型)数据库 redis作者博客,有兴趣的小伙伴可以去逛一逛:http://github.…

Android 9 蓝牙协议初始化

先讲一下Application类的使用 要使用自定义的Application,首先就是要自己新建一个Application的子类,然后把它的名字写在manifest文件里面的application标签里的android:name属性就行,如我的Application子类名字是BaseApplication&#xff0c…

Selenium 环境配置

如果你做过 Web 测试的工作,那么你应该明白 Web 测试中最重要的一部分工作就是自动化测试。自动化测试,顾名思义就是让浏览器自动运行,而无需手动操作。这和我们爬虫工作原理有些相似,我们爬虫也需要让浏览器运行网址来获取我们需…

基于QFT的量子加法器的原理与实现-mindspore quantum

1 量子Fourier变换 离散Fourier变换以一一个复向量 x 0 , . . . , x N − 1 {x_0},...,{x_{N - 1}} x0​,...,xN−1​为输入,输出的数据是如下复向量 y 0 , . . . , y N − 1 {y_0},...,{y_{N - 1}} y0​,...,yN−1​: y k ≡ 1 N ∑ j 0 N − 1 x j …

Debian12.0.0更换系统语言中文到英文

6月10号,Debian12.0.0更新,想尝尝鲜,在虚拟机里安装好,想将中文改为英文,因为Terminal下输入命令,中文切换麻烦。 一、步骤如下 #1、查看当前语言环境 env | grep LANG #2、en表示语言,US表示…

ffmpeg capture decklink

确保decklink设备已经接入 lspci | grep Blackm02:00.0 Multimedia video controller: Blackmagic Design DeckLink SDI Micro 确保decklink驱动已经正确安装 lsmod | grep blackmagicblackmagic_io 2068480 2 确保ffmpeg已经启用decklink,如何配置之前的博文已经…

岩土工程监测案例:完整链条的振弦传感器、采集仪和在线监测系统

岩土工程监测案例:完整链条的振弦传感器、采集仪和在线监测系统 在岩土工程监测中,振弦传感器被广泛应用于测量土体或岩体的振动情况,以了解地震或其他振动事件对结构物或地基的影响。振弦传感器具有高精度、快速响应、易于安装和低成本等优…

C语言指针初阶+进阶(看这一篇就够了)

目录 本章重点 1. 指针是什么 2. 指针和指针类型 3. 野指针 4. 指针运算 5. 指针和数组 6. 二级指针 7. 指针数组 8. 字符指针 9.数组指针 10. 指针数组 11数组传参和指针传参 12. 函数指针 13. 函数指针数组 14. 指向函数指针数组的指针 15. 回调函数 16 指针和数组面试题的解…

c++lambda函数笔记

1、labmda函数用途: 用于简短功能函数的定义,并传递到std算法中。 2、一般函数与lambda函数比较示例 3、如何定义lambda 如下为lambda通用定义式子: [capture] (params) opt->ret{body;}; capture——捕获列表,[]为不捕获变量…

制造执行系统(MES)的核心功能是什么?

制造执行系统(MES)的核心功能是什么? 01 什么是MES 制造执行系统(MES)是一种用于监控、控制和优化制造过程的软件系统。它通过与企业资源计划(ERP)系统和自动化系统的集成,实现对生产过程的管…

基于MATLAB的无人机遥感数据预处理与农林植被性状估算

在新一轮互联网信息技术大发展的现今,无人机、大数据、人工智能、物联网等新兴技术在各行各业都处于大爆发的前夜。为了将人工智能方法引入农业生产领域。首先在种植、养护等生产作业环节,逐步摆脱人力依赖;在施肥灌溉环节构建智慧节能系统&a…