当前位置: 首页 > news >正文

研磨设计模式day09原型模式

目录

场景

代码实现

有何问题

解决方案

代码改造 

模式讲解

原型与new

原型实例与克隆出来的实例

浅度克隆和深度克隆

原型模式的优缺点

思考

何时选用?

相关模式 


场景

代码实现

定义订单接口 

package com.zsp.bike.day08原型模式;/*** 订单的接口*/
public interface OrderApi {/*** 获取订单数量* @return*/public int getOrderProductNum();/*** 设置订单产品数量* @param num 订单产品数量*/public void setOrderProductNum(int num);
}

个人订单实现

package com.zsp.bike.day08原型模式;/*** 个人订单对象*/
public class PersonalOrder implements OrderApi{/*** 订购人员姓名*/private String customerName;/*** 产品编号*/private String productId;/*** 订单产品数量*/private int orderProductNum = 0;@Overridepublic int getOrderProductNum() {return this.orderProductNum;}@Overridepublic void setOrderProductNum(int num) {this.orderProductNum = num;}@Overridepublic String toString() {return "PersonalOrder{" +"customerName='" + customerName + '\'' +", productId='" + productId + '\'' +", orderProductNum=" + orderProductNum +'}';}public String getCustomerName() {return customerName;}public void setCustomerName(String customerName) {this.customerName = customerName;}public String getProductId() {return productId;}public void setProductId(String productId) {this.productId = productId;}}

企业订单实现

package com.zsp.bike.day08原型模式;/*** 企业订单对象*/
public class EnterpriseOrder implements OrderApi{/*** 企业名称*/private String enterpriseName;/*** 产品编号*/private String productId;/*** 订单产品数量*/private int orderProductNum = 0;@Overridepublic int getOrderProductNum() {return this.orderProductNum;}@Overridepublic void setOrderProductNum(int num) {this.orderProductNum = num;}public String getEnterpriseName() {return enterpriseName;}public void setEnterpriseName(String enterpriseName) {this.enterpriseName = enterpriseName;}public String getProductId() {return productId;}public void setProductId(String productId) {this.productId = productId;}@Overridepublic String toString() {return "EnterpriseOrder{" +"enterpriseName='" + enterpriseName + '\'' +", productId='" + productId + '\'' +", orderProductNum=" + orderProductNum +'}';}
}

通用的订单处理

package com.zsp.bike.day08原型模式;/*** 处理订单的业务对象*/
public class OrderBusiness {/*** 创建订单的方法* @param order 订单的接口对象*/public void saveOrder(OrderApi order){// 业务要求,当订单数量大于1000,把订单分成两份订单//1.判断产品数量是否大于1000while (order.getOrderProductNum() > 1000){// 2.如果大于,还需要继续拆分// 2.1 再新建一份订单,跟传入的订单除了数量不一样外,其他都相同OrderApi newOrder = null;// 如果属于个人订单if (order instanceof PersonalOrder){// 创建相应的新的订单对象PersonalOrder p2 = new PersonalOrder();// 然后进行赋值,但是产品数量为1000PersonalOrder p1 = (PersonalOrder)order;p2.setCustomerName(p1.getCustomerName());p2.setProductId(p1.getProductId());p2.setOrderProductNum(1000);// 再设置给newOrdernewOrder = p2;// 如果属于企业订单    }else if(order instanceof EnterpriseOrder){// 创建相应的订单对象EnterpriseOrder e2 = new EnterpriseOrder();// 然后进行赋值,但是产品数量为1000EnterpriseOrder e1 = (EnterpriseOrder)order;e2.setEnterpriseName(e1.getEnterpriseName());e2.setProductId(e1.getProductId());e2.setOrderProductNum(1000);// 再设置给newOrdernewOrder = e2;}// 2.2 原来的订单保留,把数量设置成减少1000order.setOrderProductNum(order.getOrderProductNum() - 1000);// 然后是业务功能处理,省略了,打印输出看一下System.out.println("拆分生成订单==" + newOrder);}//3.不超过1000,那就直接业务功能处理,省略了,打印输出看一下System.out.println("订单==" + order);}
}

客户端使用

package com.zsp.bike.day08原型模式;public class Client {public static void main(String[] args) {// 创建订单对象,这里为了演示,直接new了PersonalOrder op = new PersonalOrder();// 设置订单数据op.setOrderProductNum(2925);op.setProductId("P0001");op.setCustomerName("张三");// 这里获取业务处理的类,也直接new了OrderBusiness ob = new OrderBusiness();ob.saveOrder(op);}
}

有何问题

 简述:

1.订单处理的对象太过依赖与具体实现,划分的很细。

2.如果要增加一种新类型订单,就要增加新的订单类型支持,就要修改这个订单处理逻辑。

解决方案

原型模式

定义:

解决思路:

代码改造 

1.在订单接口里面写一个克隆自己的方法

package com.zsp.bike.day08原型模式;/*** 订单的接口*/
public interface OrderApi {/*** 获取订单数量* @return*/public int getOrderProductNum();/*** 设置订单产品数量* @param num 订单产品数量*/public void setOrderProductNum(int num);/*** 克隆方法* @return 订单原型的实例*/public OrderApi cloneOrder();
}

2.如何克隆?

千万不能return this;这么做客户端获取的都是同一个实例,都是指向同一个内存空间的,对克隆出来的对象实例进行修改会影响到原型对象实例。

 应该新建一个实例,把所有属性的值复制到新实例中。

个人订单对象修改

package com.zsp.bike.day08原型模式;/*** 个人订单对象*/
public class PersonalOrder implements OrderApi{/*** 订购人员姓名*/private String customerName;/*** 产品编号*/private String productId;/*** 订单产品数量*/private int orderProductNum = 0;@Overridepublic int getOrderProductNum() {return this.orderProductNum;}@Overridepublic void setOrderProductNum(int num) {this.orderProductNum = num;}@Overridepublic OrderApi cloneOrder() {PersonalOrder order = new PersonalOrder();order.setOrderProductNum(this.orderProductNum);order.setCustomerName(this.customerName);order.setProductId(this.productId);return order;}@Overridepublic String toString() {return "PersonalOrder{" +"customerName='" + customerName + '\'' +", productId='" + productId + '\'' +", orderProductNum=" + orderProductNum +'}';}public String getCustomerName() {return customerName;}public void setCustomerName(String customerName) {this.customerName = customerName;}public String getProductId() {return productId;}public void setProductId(String productId) {this.productId = productId;}}

 企业订单修改

package com.zsp.bike.day08原型模式;/*** 企业订单对象*/
public class EnterpriseOrder implements OrderApi{/*** 企业名称*/private String enterpriseName;/*** 产品编号*/private String productId;/*** 订单产品数量*/private int orderProductNum = 0;@Overridepublic int getOrderProductNum() {return this.orderProductNum;}@Overridepublic void setOrderProductNum(int num) {this.orderProductNum = num;}@Overridepublic OrderApi cloneOrder() {EnterpriseOrder order = new EnterpriseOrder();order.setOrderProductNum(this.orderProductNum);order.setEnterpriseName(this.enterpriseName);order.setProductId(this.productId);return order;}public String getEnterpriseName() {return enterpriseName;}public void setEnterpriseName(String enterpriseName) {this.enterpriseName = enterpriseName;}public String getProductId() {return productId;}public void setProductId(String productId) {this.productId = productId;}@Overridepublic String toString() {return "EnterpriseOrder{" +"enterpriseName='" + enterpriseName + '\'' +", productId='" + productId + '\'' +", orderProductNum=" + orderProductNum +'}';}
}

 处理订单的业务对象修改

package com.zsp.bike.day08原型模式;/*** 处理订单的业务对象*/
public class OrderBusiness {/*** 创建订单的方法* @param order 订单的接口对象*/public void saveOrder(OrderApi order){// 业务要求,当订单数量大于1000,把订单分成两份订单//1.判断产品数量是否大于1000while (order.getOrderProductNum() > 1000){// 2.如果大于,还需要继续拆分// 2.1 再新建一份订单,跟传入的订单除了数量不一样外,其他都相同OrderApi newOrder = order.cloneOrder();// 然后进行赋值,产品数量为1000newOrder.setOrderProductNum(1000);// 2.2 原来的订单保留,把数量设置成减少1000order.setOrderProductNum(order.getOrderProductNum() - 1000);// 然后是业务功能处理,省略了,打印输出看一下System.out.println("拆分生成订单==" + newOrder);}//3.不超过1000,那就直接业务功能处理,省略了,打印输出看一下System.out.println("订单==" + order);}
}

通过

 用订单的原型实例来指定对象的种类,通过克隆这个原型实例来创建出了一个新的对象实例。

模式讲解

原型模式的功能:

1.通过克隆来创建新的对象实例

2.为克隆出来的新的对象实例复制原型实例属性的值

原型与new

与new不同点在于,new出来的属性是没有值或者只有默认值,克隆出来的实例一般是有值的,它的值就是原型实例的属性的值。

原型实例与克隆出来的实例

克隆完成后,与原型实例是没有关联的,克隆出来的实例属性值发生变化不会影响原型实例。根源在于不是return this; 是复制的,是指向不同内存空间的

需要克隆的类,可以实现java.lang.Cloneable

浅度克隆和深度克隆

 

原型模式的优缺点

思考

原型模式的本质:克隆生成对象

创建型模式

何时选用?

相关模式 

 

 

相关文章:

研磨设计模式day09原型模式

目录 场景 代码实现 有何问题 解决方案 代码改造 模式讲解 原型与new 原型实例与克隆出来的实例 浅度克隆和深度克隆 原型模式的优缺点 思考 何时选用? 相关模式 场景 代码实现 定义订单接口 package com.zsp.bike.day08原型模式;/*** 订单的接口*…...

(二)Redis——List

因为是 List,所以所有相关的命令都以 L 开头。 LPUSH / RPUSH LRANGE list 0 -1 -1 表示末尾 127.0.0.1:6379> LPUSH list a 1 127.0.0.1:6379> LRANGE list 0 -1 a 127.0.0.1:6379> LPUSH list b 2 127.0.0.1:6379> LRANGE list 0 -1 b a 127.0.0.…...

【Go Web 篇】Go 语言进行 Web 开发:构建高性能网络应用

随着互联网的快速发展,Web 开发已经成为了软件开发领域中不可或缺的一部分。随之而来的是对于更高性能、更高效的网络应用的需求。在这个领域,Go 语言因其并发性能、简洁的语法以及丰富的标准库而备受关注。本篇博客将深入探讨如何使用 Go 语言进行 Web …...

开悟Optimization guide for intermediate tracks

目录 认识模型 参考方案(按模块拆解) 认识模型 模型控制1名英雄进行镜像1 v 1对战 Actor集群资源为64核CPU 问题特点:单一公平对抗场景(同英雄镜像对赛),单位时间样本产能低,累计训练资源相…...

wx.request配置服务器域名,只能包含英文大小写字母、数字,解决办法

前言.小程序服务器域名配置常见错误及解决方法 1.配置入口: 小程序后台->-开发->开发设置->服务器域名 2.常见错误及原因分析: 3.实战中出现的错误 4.解决办法:应把域名后边的路径去掉,只写域名即可...

【有效的括号】

题目 1、左括号入栈 2、右括号出栈顶括号进行匹配 栈 typedef char STDataType; //元素为char类型 typedef struct Stack {STDataType* a;//动态的开辟空间int top;int capacity; }ST;void StackInit(ST* ps)//初始化 {assert(ps);ps->a (STDataType*)malloc(sizeof(STD…...

积跬步至千里 || 数学基础、算法与编程

数学基础、算法与编程 1. BAP 技能 BAP 技能是指基础(Basic)、算法(Algorithm)和编程(Programm)三种基本技能的深度融合。理工科以数学、算法与编程为根基,这三个相辅相成又各有区别。 (1)数学以线性代数为主要研究工具和部分微积分技术为手…...

Java单元测试 JUnit 5 快速上手

一、背景 什么是 JUnit 5?首先就得聊下 Java 单元测试框架 JUnit,它与另一个框架 TestNG 占据了 Java领域里单元测试框架的主要市场,其中 JUnit 有着较长的发展历史和不断演进的丰富功能,备受大多数 Java 开发者的青睐。 而说到…...

【Linux网络】TCP UDP socket HTTP webSocket之间的区别

目录 一、OSI & TCP/IP模型 二、几者之间的关系 三、HTTP 四、Socket 五、WebSocket 5.1、WebSocket 优点 一、OSI & TCP/IP模型 首先我们要了解OSI七层模型,和预支对应的TCP/IP 四层的模型。 用下面的图可以看出,TCP UDP 工作在传输层&…...

【面向大一新生IT技术社群招新啦,不来瞅瞅?】

个人名片: 🐼作者简介:一名大三在校生 🐻‍❄️个人主页:落798. 🐼个人WeChat:落798. 🕊️系列专栏:【零基础学java】 ----- 【重识c语言】 ---- 【计算机网络】—【Spri…...

分析系统 - 使用Python爬虫

在竞争激烈的市场环境中,了解和分析竞争对手的销售策略和市场表现对于企业的成功至关重要。本文将介绍如何利用Python爬虫建立低成本的销售竞争对手分析系统,探索其方法、工具和好处,并同时解决可能出现的问题。 销售竞争对手分析的目标是获取…...

strstr函数

目录 函数介绍: 函数分析: ​使用案例: 函数介绍: 返回指向 str1 中第一次出现的 str2 的指针,如果 str2 不是 str1 的一部分,则返回一个空指针。 匹配过程不包括终止空字符,但它到此为止。 …...

[C++] string类常用接口的模拟实现

文章目录 1、前言2、遍历2.1 operator[ ]下标方式2.2 迭代器2.3 范围for2.4 c_str 3、容量相关3.1 size(大小)3.2 capacity(容量)3.3 empty(判空)3.4 clear(清理)3.5 reserve3.6 res…...

每日一学——防火墙

防火墙是网络安全的重要组成部分,可以帮助保护网络免受恶意攻击和未经授权的访问。以下是防火墙的基本配置步骤: 定义安全策略:防火墙通过安全策略来决定允许或拒绝网络流量。你需要定义适当的安全策略来保护你的网络。安全策略通常包括源IP地…...

常用数据库备份方法,sql数据库备份方法

在信息时代,数据成为了公司的主要资产。然而,数据的安全性和完整性也成为企业管理的重要组成部分。因此,数据库备份至关重要。本文将详细介绍几种常见的数据库备份方法。 全备份 全备份是指数据库中所有数据的备份,包括数据文件、…...

常见前端面试之VUE面试题汇总八

22. Vue 子组件和父组件执行顺序 加载渲染过程: 1.父组件 beforeCreate 2.父组件 created 3.父组件 beforeMount 4.子组件 beforeCreate 5.子组件 created 6.子组件 beforeMount 7.子组件 mounted 8.父组件 mounted 更新过程: 1. 父组件 befor…...

弯道超车必做好题集锦二(C语言选择题)

前言: 编程想要学的好,刷题少不了,我们不仅要多刷题,还要刷好题!为此我开启了一个弯道超车必做好题锦集的系列,每篇大约10题左右。此为第二篇选择题篇,该系列会不定期更新,后续还会…...

PROFIBUS主站转MODBUS TCP网关

1.产品功能 YC-DPM-TCP网关在Profibus总线侧实现主站功能,在以太网侧实现ModbusTcp服务器功能。可将Profibus DP从站接入到ModbusTcp网络;通过增加DP/PA耦合器,也可将Profibus PA从站接入ModbusTcp网络。YC-DPM-TCP网关最多支持125个Profibu…...

【力扣】盛最多水的容器

目录 题目 题目初步解析 水桶效应 代码实现逻辑 第一步 第二步 第三步 代码具体实现 注意 添加容器元素的函数 计算迭代并且判断面积是否是最大值 总代码 运行结果 总结 题目 给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是…...

【SQL应知应会】索引(三)• MySQL版:聚簇索引与非聚簇索引;查看索引与删除索引;索引方法

欢迎来到爱书不爱输的程序猿的博客, 本博客致力于知识分享,与更多的人进行学习交流 本文收录于SQL应知应会专栏,本专栏主要用于记录对于数据库的一些学习,有基础也有进阶,有MySQL也有Oracle 索引 • MySQL版 前言一、索引1.简介2.索引类型之逻…...

Python|GIF 解析与构建(5):手搓截屏和帧率控制

目录 Python|GIF 解析与构建(5):手搓截屏和帧率控制 一、引言 二、技术实现:手搓截屏模块 2.1 核心原理 2.2 代码解析:ScreenshotData类 2.2.1 截图函数:capture_screen 三、技术实现&…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

VB.net复制Ntag213卡写入UID

本示例使用的发卡器:https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具

文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

NLP学习路线图(二十三):长短期记忆网络(LSTM)

在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)

文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...

【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)

1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...

AI,如何重构理解、匹配与决策?

AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...

重启Eureka集群中的节点,对已经注册的服务有什么影响

先看答案,如果正确地操作,重启Eureka集群中的节点,对已经注册的服务影响非常小,甚至可以做到无感知。 但如果操作不当,可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...

MySQL JOIN 表过多的优化思路

当 MySQL 查询涉及大量表 JOIN 时,性能会显著下降。以下是优化思路和简易实现方法: 一、核心优化思路 减少 JOIN 数量 数据冗余:添加必要的冗余字段(如订单表直接存储用户名)合并表:将频繁关联的小表合并成…...