【设计模式活用】之代码重构之DAO扮演多个职责的重构案例

2023-12-03 12:58

本文主要是介绍【设计模式活用】之代码重构之DAO扮演多个职责的重构案例,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在本次关于GPS优化需求项目时,发现相关功能菜单查询页面共同一个DAO接口实现类,紧接着我看了一下listAll,pre,next,countAll方法业务代码高度相似,此已说明该DAO扮演着非单一原则,其承担着 系统多个功能菜单的查询功能。

文章目录

  • 1.背景介绍
    • 1.1 业务分析
    • 1.2 思路分析
  • 2、相关类图
    • 2.1、executor类图
    • 2.2、context类图
  • 3、相关源码
    • 3.1、AbstractWhereExecutor
    • 3.2、InstalledGpsQueryExecutor
    • 3.3、TobeUploadGpsQueryExecutor
    • 3.4、UnInstalledGpsQueryExecutor
    • 3.5、UploadedGpsQueryExecutor
    • 3.6、调用方
  • 4、归纳总结

1.背景介绍

  • 共同之处,就是查询共同表 ca_app_info,或者操作共同Hibernate对象VCaAppInfo。

  • 不同之处体现如下方面:1、包含HQL和SQL查询 。2、where条件不同(为了过滤数据以及根据页面表单条件动态判断拼加成一个StringBuffer对象(即SQL/HQL))。

1.1 业务分析

涉及查询的四个方法中(listAll,pre,next,countAll方法业务代码高度相似),代码冗余,不利于维护。

因此,借此机遇,对涉及本期需求GPS查询 四个页面进行重构,提炼出四个单据的实现类,统一继承抽象类,内部维护相关SQL或者HQL查询逻辑,调用方只需构造上线文,

产生不同的实现类即可,提高可扩展,可维护性。重构前代码,点击链接,查看方法:listAll,pre,next,countAll,你就晓得了。

源代码片段

@Overridepublic List<VCaAppInfo> pre(VCaAppInfoId ci, int pn, int defaultPageSize) {// TODO Auto-generated method stubStringBuffer sb = new StringBuffer();sb.append("from VCaAppInfo v where 1=1");List<Object> listParams = new ArrayList<Object>();AbstractWhereExecutor<VCaAppInfoId> whereExecutor;WhereContext whereContext = new WhereContext(ci,sb,listParams,WhereContext.Strategy.HQL);String status = ci.getStatus();if (StringUtil.checkStatus(status)) {sb.append(" and v.id.status in (?)");listParams.add(status);sb.append(" and v.AUserId=? ");listParams.add(ci.getUser().getUserId());/** if("23".equals(status)){ //根据REFUSE_STATUS拒绝状态查询* sb.append(" and v.refuseStatus in (?)");* listParams.add(ci.getRefusestatus()); }else* if("24".equals(status)){ sb.append(" and v.refuseStatus <> 3"); }*/if ("23".equals(status)) { // 根据REFUSE_STATUS拒绝状态查询sb.append(" and v.refuseStatus in (?)");listParams.add(ci.getRefusestatus());} else if ("24".equals(status) && !"3".equals(ci.getRefusestatus())) { // refusestatus// =// 0// 1// 终审sb.append(" and v.refuseStatus <> 3");} else if ("3".equals(ci.getRefusestatus())) { // 3 复核拒绝sb.append(" and v.refuseStatus = 3");}} else if ("80".equals(ci.getStatus())) { // 复审审批页面 显示自己审批的和信贷经理退回审批的// 150123sb.append(" and v.id.status in('23','30')");sb.append(" and v.AUserId=? ");listParams.add(ci.getUser().getUserId());} else if ("-27".equals(status)) { // 经销商上传GPS安装单 150302sb.append(" and (v.isGps ='0' or v.isGps ='2') and v.gpsFee<>0 and v.gpsFee !='' and v.gpsFee is not null and v.manageApprovalTime is not null and v.id.status not in('11','12') ");// 经销商用户只能查看该门店单子 其他用户查看所有Set<SyUserDealer> ds = ci.getUser().getSyUserDealers();if (ds.size() != 0) {sb.append(" and v.id.dealerCode in(");Iterator<SyUserDealer> it = ci.getUser().getSyUserDealers().iterator();while (it.hasNext()) {SyUserDealer d = it.next();int dealerCode = d.getId().getDealerCode();sb.append(dealerCode + " ,");}String allhql = sb.substring(0, sb.length() - 1);allhql += ") ";sb.setLength(0);// 清空 后加上sb.append(allhql);}} else if ("-28".equals(status)) { // GPS维护 已上传GPS安装whereExecutor = new InstalledGpsQueryExecutor(whereContext);whereExecutor.execute();} else if ("-29".equals(status)) { // GPS维护whereExecutor = new UnInstallGpsQueryExecutor(whereContext);whereExecutor.execute();} else if ("-30".equals(status)) { // 贷后资料维护sb.append(" and (v.ALOANARRIVE is null or v.ALOANARRIVE!='1') and v.id.status='32' ");if (ci.getIsOld() != null) {sb.append(" and v.isOld=? ");listParams.add(ci.getIsOld());}if (ci.getPostLoanStatus() != null) {// 新车贷后资料上传状态(包括花乡的二手车 即先放款后抵押)if ("0".equals(ci.getPostLoanStatus())) {// 未上传sb.append(" and (v.postLoanStatus is null or v.postLoanStatus='0' ) ");} else if ("1".equals(ci.getPostLoanStatus())) {// 已上传sb.append(" and v.postLoanStatus='1' ");} else if ("2".equals(ci.getPostLoanStatus())) {// 审批退回sb.append(" and v.postLoanStatus='2' ");} else if ("3".equals(ci.getPostLoanStatus())) {// 审批通过sb.append(" and v.postLoanStatus='3' ");}}} else if ("-31".equals(status)) { // 贷后资料维护回退sb.append(" and v.ALOANARRIVE='1' and v.id.status='32' ");} else if ("-32".equals(status)) { // 新车等待上传贷后资料sb.append(" and v.id.status='32' and ifnull(v.ALOANARRIVE,'')!='1' ");if (ci.getIsOld() != null) {sb.append(" and v.isOld=? ");listParams.add(ci.getIsOld());}if (ci.getPostLoanStatus() != null) {if ("0".equals(ci.getPostLoanStatus())) {// 未上传sb.append(" and (v.postLoanStatus is null or v.postLoanStatus='0') ");} else if ("1".equals(ci.getPostLoanStatus())) {// 已上传sb.append(" and v.postLoanStatus='1' ");} else if ("2".equals(ci.getPostLoanStatus())) {// 审批退回sb.append(" and v.postLoanStatus='2' ");} else if ("3".equals(ci.getPostLoanStatus())) {// 审批通过sb.append(" and v.postLoanStatus='3' ");}} else {sb.append(" and ifnull(v.postLoanStatus,'')!='1' and ifnull(v.postLoanStatus,'')!='3' ");// 所有,不显示已上传的申请单和审批通过的}// 经销商用户只能查看该门店单子 其他用户查看所有Set<SyUserDealer> ds = ci.getUser().getSyUserDealers();if (ds.size() != 0) {sb.append(" and v.id.dealerCode in(");Iterator<SyUserDealer> it = ci.getUser().getSyUserDealers().iterator();while (it.hasNext()) {SyUserDealer d = it.next();int dealerCode = d.getId().getDealerCode();sb.append(dealerCode + " ,");}String allhql = sb.substring(0, sb.length() - 1);allhql += ") ";sb.setLength(0);// 清空 后加上sb.append(allhql);}} else if ("-33".equals(status)) {// 经销商GPS安装列表,TODO zhaozhaoxin// 20170411 addsb.append(" and v.gpsFee<>0 and v.gpsFee !='' and v.gpsFee is not null and v.manageApprovalTime is not null and status in('15','16','17','18','19','25','26','27','28','29','32') ");// 经销商用户只能查看该门店单子 其他用户查看所有Set<SyUserDealer> ds = ci.getUser().getSyUserDealers();if (ds.size() != 0) {sb.append(" and v.id.dealerCode in(");Iterator<SyUserDealer> it = ci.getUser().getSyUserDealers().iterator();while (it.hasNext()) {SyUserDealer d = it.next();int dealerCode = d.getId().getDealerCode();sb.append(dealerCode + " ,");}String allhql = sb.substring(0, sb.length() - 1);allhql += ") ";sb.setLength(0);// 清空 后加上sb.append(allhql);}} else {sb.append(" and v.id.status in (?)");listParams.add(status);// TODO zhaozhaoxin 20170308 add 进行分组查询if (isRoleQueryData(ci.getUser())) {getUserGroupIds(sb, ci.getUser(), status, true);} else {return null;}}if (ci.getFlowSeq() != null) {sb.append(" and v.flowSeq= ?");listParams.add(ci.getFlowSeq());}if (ci.getDealerName() != null) {sb.append(" and v.id.dealerName like ?");listParams.add("%" + ci.getDealerName() + "%");}if (ci.getAppCode() != null) {sb.append(" and v.id.appCode = ?");listParams.add(ci.getAppCode());}if (ci.getProppserName() != null) {sb.append(" and v.id.proppserName like ?");listParams.add("%" + ci.getProppserName() + "%");}if (ci.getIsLcv() != null) {sb.append(" and v.isLcv = ?");listParams.add(ci.getIsLcv());}if (ci.getAppTime() != null) {sb.append(" and date_format(v.id.appTime,'%Y%m%d') >= ?");listParams.add(DateUtil.getDateFormatE(ci.getAppTime()));}if (ci.getAppTime2() != null) {sb.append(" and date_format(v.id.appTime,'%Y%m%d') <= ?");listParams.add(DateUtil.getDateFormatE(ci.getAppTime2()));}if (ci.getUpdateTime1() != null) {sb.append(" and date_format(v.updateTime,'%Y%m%d') >= ?");listParams.add(DateUtil.getDateFormatE(ci.getUpdateTime1()));}if (ci.getUpdateTime2() != null) {sb.append(" and date_format(v.updateTime,'%Y%m%d') <= ?");listParams.add(DateUtil.getDateFormatE(ci.getUpdateTime2()));}if (ci.getLoanDate1() != null) {sb.append(" and date_format(v.loanTime,'%Y%m%d') >= ?");listParams.add(DateUtil.getDateFormatE(ci.getLoanDate1()));}if (ci.getLoanDate2() != null) {sb.append(" and date_format(v.loanTime,'%Y%m%d') <= ?");listParams.add(DateUtil.getDateFormatE(ci.getLoanDate2()));}sb.append(" order by v.updateTime asc");// 从小到大排序 先提交的在前面List<VCaAppInfo> result = queryByHql(sb.toString(), pn,defaultPageSize, listParams.toArray());return result;}

1.2 思路分析

涉及四个功能菜单

  • 1、待上传GPS安装单
  • 2、GPS安装单列表
  • 3、GPS安装单未上传
  • 4、GPS安装单已上传

思路:分析如上四个菜单的查询特征,通过把相同和差异的抽象出来,即提取一个抽象类,通过模板方法,差异部分为抽象类子类,实现差异部分业务逻辑。

2、相关类图

2.1、executor类图

类图概览

2.2、context类图

context类图

3、相关源码

3.1、AbstractWhereExecutor

public abstract class AbstractWhereExecutor<T> implements Predicate<WhereContext> {/*** 上线文*/protected WhereContext<T> context;/*** 参数DTO*/protected T dto;/*** 查询条件*/protected StringBuffer queryWhere;/*** 构造函数* @param context 上线文对象*/public AbstractWhereExecutor(WhereContext<T> context) {this.context = context;}/*** 处理接口*/public void execute() {this.execute((e)->{});}/*** 处理接口* @param after*/public void execute(Consumer<WhereContext> after) {// 初始化this.prepare();// 检查参数this.check(context);// 执行鉴定if(this.test(context)){switch (context.getStrategy()){case SQL:sql();break;case HQL:hql();break;default:break;}}// 后置处理after.accept(context);}/*** 参数检查* @param context*/protected void check(WhereContext context){Assert.notNull(context.getDto(),"DTO对象为空");Assert.notNull(context.getStrategy(),"strategy为空");}/*** 初始化参数*/protected void prepare(){this.dto = this.context.getDto();this.queryWhere = this.context.getQueryWhere();}/*** 由子类实现具体处理SQL条件*/protected abstract void sql();/*** 由子类实现具体处理HQL条件*/protected abstract void hql();
}

3.2、InstalledGpsQueryExecutor

public class InstalledGpsQueryExecutor extends AbstractWhereExecutor<VCaAppInfoId> {/*** 标示*/protected String gpsFlow;/*** 审批人*/protected Integer approvalUserId;/*** 构造函数** @param context 上线文对象*/public InstalledGpsQueryExecutor(WhereContext context) {super(context);}@Overrideprotected void check(WhereContext context) {super.check(context);SyUser sessionUser = dto.getUser();Assert.notNull(sessionUser,"sessionUser为空");}@Overrideprotected void prepare() {super.prepare();this.gpsFlow = dto.getGpsFlow();this.approvalUserId = dto.getUser().getUserId();}@Overrideprotected void sql() {VCaAppInfoId dto = super.dto;StringBuffer where = super.queryWhere;if(this.isMine()){where.append(" and exists(select 1 from ca_gps_flow f where f.app_code = v.app_code and f.flow_step = 0 and f.approval_user_id = "+this.approvalUserId+") ");}where.append(" and v.status not in (11,13) and v.is_Gps ='2' and v.gps_Fee<>0 and v.gps_Fee !='' and v.gps_Fee is not null  and v.manage_Approval_Time is not null");if(!StringUtil.isBlank(dto.getProvince())){where.append(" and exists(select 1 from Sy_Dealer dr where dr.province = '"+dto.getProvince()+"' and dr.dealer_Code =  v.dealer_Code) ");}if (!StringUtil.isBlank(dto.getPostLoanStatus())) {//由于manual_audit_code多个时以";"分割,所以需要使用FIND_IN_SET函数处理 add by 石冬冬 on 2017/9/21where.append(" and v.app_code IN (SELECT app_code FROM Ca_Car_Gps WHERE del_status=1 and FIND_IN_SET ("+dto.getPostLoanStatus()+",replace(manual_audit_code,';',','))>0 ");where.append(" GROUP BY app_code) ");}}@Overrideprotected void hql() {VCaAppInfoId dto = super.dto;StringBuffer where = super.queryWhere;if(this.isMine()){where.append(" and exists(select 1 from CaGpsFlow f where f.appCode = v.id.appCode and f.flowStep = 0 and f.approvalUserId = " + this.approvalUserId+")");}where.append(" and v.id.status not in (11,13) and v.isGps ='2' and v.gpsFee<>0 and v.gpsFee !='' and v.gpsFee is not null and v.manageApprovalTime is not null");if(!StringUtil.isBlank(dto.getProvince())){where.append(" and exists(select 1 from SyDealer dr where dr.province = '"+dto.getProvince()+"' and dr.dealerCode =  v.id.dealerCode) ");}if (!StringUtil.isBlank(dto.getPostLoanStatus())) {//由于manual_audit_code多个时以";"分割,所以需要使用FIND_IN_SET函数处理 add by 石冬冬 on 2017/9/21where.append(" and v.id.appCode IN (SELECT appCode FROM CaCarGps WHERE delStatus=1 and find_in_set("+dto.getPostLoanStatus()+",replace(manualAuditCode,';',','))>0 ");where.append(" GROUP BY appCode) ");}}@Overridepublic boolean test(WhereContext context) {VCaAppInfoId dto = (VCaAppInfoId)context.getDto();return "-28".equals(dto.getStatus());}private boolean isMine(){return "mine".equals(gpsFlow);}
}

3.3、TobeUploadGpsQueryExecutor

public class TobeUploadGpsQueryExecutor extends AbstractWhereExecutor<VCaAppInfoId> {/*** 构造函数** @param context 上线文对象*/public TobeUploadGpsQueryExecutor(WhereContext context) {super(context);}@Overrideprotected void check(WhereContext context) {super.check(context);SyUser sessionUser = dto.getUser();Assert.notNull(sessionUser,"sessionUser为空");}@Overrideprotected void sql() {StringBuffer where = super.queryWhere;SyUser sessionUser = dto.getUser();where.append(" and (v.is_Gps ='0' or v.is_Gps ='2') and v.gps_Fee<>0 and v.gps_Fee !='' and v.gps_Fee is not null  and v.manage_Approval_Time is not null and v.status not in('11','12') ");GpsUtil.appendDealerCodes(sessionUser,(list) -> {String condition = MessageFormat.format(" and v.dealer_Code in({0})", StringUtils.join(list,","));where.append(condition);});}@Overrideprotected void hql() {StringBuffer where = super.queryWhere;SyUser sessionUser = dto.getUser();where.append(" and (v.isGps ='0' or v.isGps ='2') and v.gpsFee<>0 and v.gpsFee !='' and v.gpsFee is not null and v.manageApprovalTime is not null and v.id.status not in('11','12') ");GpsUtil.appendDealerCodes(sessionUser,(list) -> {String condition = MessageFormat.format(" and v.id.dealerCode in({0})", StringUtils.join(list,","));where.append(condition);});}@Overridepublic boolean test(WhereContext context) {VCaAppInfoId dto = (VCaAppInfoId)context.getDto();return "-27".equals(dto.getStatus());}
}

3.4、UnInstalledGpsQueryExecutor

/*** @description: 车贷审批管理》GPS安装单未上传* @Date : 上午10:17 2017/11/17* @Author : 石冬冬-Heil Hitler(dongdong.shi@mljr.com)*/
public class UnInstalledGpsQueryExecutor extends AbstractWhereExecutor<VCaAppInfoId> {/*** 标示*/protected String gpsFlow;/*** 审批人*/protected Integer approvalUserId;/*** 构造函数** @param context 上线文对象*/public UnInstalledGpsQueryExecutor(WhereContext context) {super(context);}@Overrideprotected void check(WhereContext context) {super.check(context);SyUser sessionUser = dto.getUser();Assert.notNull(sessionUser,"sessionUser为空");}@Overrideprotected void prepare() {super.prepare();this.gpsFlow = dto.getGpsFlow();this.approvalUserId = dto.getUser().getUserId();}@Overrideprotected void sql() {StringBuffer where = super.queryWhere;if(this.isMine()){where.append(" and exists(select 1 from ca_gps_flow f where f.app_code = v.app_code and f.flow_step = 0 and f.approval_user_id = "+this.approvalUserId+")");}where.append(" and v.status not in (11,13) and v.is_Gps ='0' and v.gps_Fee<>0 and v.gps_Fee !='' and v.gps_Fee is not null  and v.manage_Approval_Time is not null");if(!StringUtil.isBlank(dto.getProvince())){where.append(" and exists(select 1 from Sy_Dealer dr where dr.province = '"+dto.getProvince()+"' and dr.dealer_Code =  v.dealer_Code) ");}}@Overrideprotected void hql() {VCaAppInfoId dto = super.dto;StringBuffer where = super.queryWhere;if(this.isMine()){where.append(" and exists(select 1 from CaGpsFlow f where f.appCode = v.id.appCode and f.flowStep = 0 and f.approvalUserId = "+this.approvalUserId+")");}where.append(" and v.id.status not in (11,13) and v.isGps ='0' and v.gpsFee<>0 and v.gpsFee !='' and v.gpsFee is not null and v.manageApprovalTime is not null");if(!StringUtil.isBlank(dto.getProvince())){where.append(" and exists(select 1 from SyDealer dr where dr.province = '"+dto.getProvince()+"' and dr.dealerCode =  v.id.dealerCode) ");}}@Overridepublic boolean test(WhereContext context) {VCaAppInfoId dto = (VCaAppInfoId)context.getDto();return "-29".equals(dto.getStatus());}private boolean isMine(){return "mine".equals(gpsFlow);}
}

3.5、UploadedGpsQueryExecutor

public class UploadedGpsQueryExecutor extends AbstractWhereExecutor<VCaAppInfoId> {private final String STATUS_SCOPE = "'15','16','17','18','19','25','26','27','28','29','32'";/*** 构造函数** @param context 上线文对象*/public UploadedGpsQueryExecutor(WhereContext context) {super(context);}@Overrideprotected void check(WhereContext context) {super.check(context);SyUser sessionUser = dto.getUser();Assert.notNull(sessionUser,"sessionUser为空");}@Overrideprotected void sql() {VCaAppInfoId dto = super.dto;StringBuffer where = super.queryWhere;SyUser sessionUser = dto.getUser();where.append(" and v.gps_Fee<>0 and v.gps_Fee !='' and v.gps_Fee is not null  and v.manage_Approval_Time is not null and status in("+STATUS_SCOPE+") ");GpsUtil.appendDealerCodes(sessionUser,(list) -> {String condition = MessageFormat.format(" and v.dealer_Code in({0})", StringUtils.join(list,","));where.append(condition);});}@Overrideprotected void hql() {VCaAppInfoId dto = super.dto;StringBuffer where = super.queryWhere;SyUser sessionUser = dto.getUser();where.append(" and v.gpsFee<>0 and v.gpsFee !='' and v.gpsFee is not null and v.manageApprovalTime is not null and status in("+STATUS_SCOPE+") ");GpsUtil.appendDealerCodes(sessionUser,(list) -> {String condition = MessageFormat.format(" and v.id.dealerCode in({0})", StringUtils.join(list,","));where.append(condition);});}@Overridepublic boolean test(WhereContext context) {VCaAppInfoId dto = (VCaAppInfoId)context.getDto();return "-33".equals(dto.getStatus());}
}

3.6、调用方

入口

4、归纳总结

如上,即使用了模板方法这个设计模式,模板方法也是最通常使用的,即把相同的逻辑骨架抽象处理,由子类实现各自的差异部门。

下面的是我的公众号二维码图片,欢迎关注,或公众号搜索【秋夜无霜】。
秋夜无霜

这篇关于【设计模式活用】之代码重构之DAO扮演多个职责的重构案例的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/449537

相关文章

使用Java将DOCX文档解析为Markdown文档的代码实现

《使用Java将DOCX文档解析为Markdown文档的代码实现》在现代文档处理中,Markdown(MD)因其简洁的语法和良好的可读性,逐渐成为开发者、技术写作者和内容创作者的首选格式,然而,许多文... 目录引言1. 工具和库介绍2. 安装依赖库3. 使用Apache POI解析DOCX文档4. 将解析

C++使用printf语句实现进制转换的示例代码

《C++使用printf语句实现进制转换的示例代码》在C语言中,printf函数可以直接实现部分进制转换功能,通过格式说明符(formatspecifier)快速输出不同进制的数值,下面给大家分享C+... 目录一、printf 原生支持的进制转换1. 十进制、八进制、十六进制转换2. 显示进制前缀3. 指

Python中使用正则表达式精准匹配IP地址的案例

《Python中使用正则表达式精准匹配IP地址的案例》Python的正则表达式(re模块)是完成这个任务的利器,但你知道怎么写才能准确匹配各种合法的IP地址吗,今天我们就来详细探讨这个问题,感兴趣的朋... 目录为什么需要IP正则表达式?IP地址的基本结构基础正则表达式写法精确匹配0-255的数字验证IP地

MySQL高级查询之JOIN、子查询、窗口函数实际案例

《MySQL高级查询之JOIN、子查询、窗口函数实际案例》:本文主要介绍MySQL高级查询之JOIN、子查询、窗口函数实际案例的相关资料,JOIN用于多表关联查询,子查询用于数据筛选和过滤,窗口函... 目录前言1. JOIN(连接查询)1.1 内连接(INNER JOIN)1.2 左连接(LEFT JOI

使用Python实现全能手机虚拟键盘的示例代码

《使用Python实现全能手机虚拟键盘的示例代码》在数字化办公时代,你是否遇到过这样的场景:会议室投影电脑突然键盘失灵、躺在沙发上想远程控制书房电脑、或者需要给长辈远程协助操作?今天我要分享的Pyth... 目录一、项目概述:不止于键盘的远程控制方案1.1 创新价值1.2 技术栈全景二、需求实现步骤一、需求

Java中Date、LocalDate、LocalDateTime、LocalTime、时间戳之间的相互转换代码

《Java中Date、LocalDate、LocalDateTime、LocalTime、时间戳之间的相互转换代码》:本文主要介绍Java中日期时间转换的多种方法,包括将Date转换为LocalD... 目录一、Date转LocalDateTime二、Date转LocalDate三、LocalDateTim

jupyter代码块没有运行图标的解决方案

《jupyter代码块没有运行图标的解决方案》:本文主要介绍jupyter代码块没有运行图标的解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录jupyter代码块没有运行图标的解决1.找到Jupyter notebook的系统配置文件2.这时候一般会搜索到

Python通过模块化开发优化代码的技巧分享

《Python通过模块化开发优化代码的技巧分享》模块化开发就是把代码拆成一个个“零件”,该封装封装,该拆分拆分,下面小编就来和大家简单聊聊python如何用模块化开发进行代码优化吧... 目录什么是模块化开发如何拆分代码改进版:拆分成模块让模块更强大:使用 __init__.py你一定会遇到的问题模www.

Java编译生成多个.class文件的原理和作用

《Java编译生成多个.class文件的原理和作用》作为一名经验丰富的开发者,在Java项目中执行编译后,可能会发现一个.java源文件有时会产生多个.class文件,从技术实现层面详细剖析这一现象... 目录一、内部类机制与.class文件生成成员内部类(常规内部类)局部内部类(方法内部类)匿名内部类二、

springboot循环依赖问题案例代码及解决办法

《springboot循环依赖问题案例代码及解决办法》在SpringBoot中,如果两个或多个Bean之间存在循环依赖(即BeanA依赖BeanB,而BeanB又依赖BeanA),会导致Spring的... 目录1. 什么是循环依赖?2. 循环依赖的场景案例3. 解决循环依赖的常见方法方法 1:使用 @La