模板方法模式(继承的优雅使用)
目录
前言
UML
plantuml
类图
实战代码
AbstractRoutingDataSource
DynamicDataSource
DynamicDataSourceContextHolder
前言
在设计类时,一般优先考虑使用组合来替代继承,能够让程序更加的灵活,但这并不意味着要完全抛弃掉继承。
继承在面向对象编程中用来减少代码冗余和提高复用性,是面向对象编程的一大特性。
只不过在使用继承时必须满足一些条件,才能让我们更好地利用继承,设计出更易维护和扩展的程序。
一般情况下,使用继承需要满足一下两个条件
- 父类所有的属性和方法,都能在子类中适用
- 子类无需复用其他类的方法,并且不会覆写父类已有的方法
模板方法模式是继承使用的优雅示例,一般会设计一个抽象类,在类中定义了一个操作的算法结构,其中一些步骤被设计为抽象方法,需要子类去实现,这些方法被称为模板方法。
模板方法允许子类在不改变算法结构的情况下,重新定义算法的某些特定步骤。
UML
plantuml
@startuml
'https://plantuml.com/class-diagramabstract Template {+ doSomething() : void- step1() : void- step2() : void+ {abstract} step3() : void
}class Concrete {+ step3() : void
}class Client {}Template <|-- ConcreteClient ..> Concrete
@enduml
类图

实战代码
AbstractRoutingDataSource
业务上需要用到动态数据源,可以继承 spring 框架提供的抽象类 AbstractRoutingDataSource 来实现运行中动态切换数据源功能。
初始化动态数据源时,将所有的数据源都保存在 private Map<Object, DataSource> resolvedDataSources 中,每一个数据源对应一个唯一标识。
抽象类定义了决定目标数据源的方法(determineTargetDataSource),用来决定当前操作要使用动态数据源中的哪一个数据源,方法中调用了模板方法(determineCurrentLookupKey),子类只需要实现 determineCurrentLookupKey 这个模板方法,动态地返回数据源唯一标识,便能够实现动态切换数据源了
determineTargetDataSource 与 determineCurrentLookupKey

DynamicDataSource
public class DynamicDataSource extends AbstractRoutingDataSource {public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {super.setDefaultTargetDataSource(defaultTargetDataSource);super.setTargetDataSources(targetDataSources);super.afterPropertiesSet();}@Overrideprotected Object determineCurrentLookupKey() {return DynamicDataSourceContextHolder.getDataSourceType();}
}
DynamicDataSourceContextHolder
public class DynamicDataSourceContextHolder {/*** 使用ThreadLocal维护变量,ThreadLocal为每个使用该变量的线程提供独立的变量副本,* 所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。*/private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();/*** 设置数据源变量* @param dataSourceType*/public static void setDataSourceType(String dataSourceType){System.out.printf("切换到{%s}数据源", dataSourceType);CONTEXT_HOLDER.set(dataSourceType);}/*** 获取数据源变量* @return*/public static String getDataSourceType(){return CONTEXT_HOLDER.get();}/*** 清空数据源变量*/public static void clearDataSourceType(){CONTEXT_HOLDER.remove();}
}相关文章:
模板方法模式(继承的优雅使用)
目录 前言 UML plantuml 类图 实战代码 AbstractRoutingDataSource DynamicDataSource DynamicDataSourceContextHolder 前言 在设计类时,一般优先考虑使用组合来替代继承,能够让程序更加的灵活,但这并不意味着要完全抛弃掉继承。 …...
百度智能云千帆,产业创新新引擎
本文整理自 3 月 21 日百度副总裁谢广军的主题演讲《百度智能云千帆,产业创新新引擎》。 各位领导、来宾、媒体朋友们,大家上午好。很高兴今天在石景山首钢园,和大家一起沟通和探讨大模型的发展趋势,以及百度最近一段时间的思考和…...
Python下载cuda包失败后到成功(方便使用GPU加速运算,显著提高代码运行速度)
一、查询自己电脑上的cuda版本方法: 1.在windows的cmd里查询显卡cuda的版本号,命令行输入:nvidia-smi 2.在NVIDIA控制面板上寻找自己电脑上cuda的版本 二、安装支持的cuda的python cupy库 因为我的电脑上为cuda11.4,所以使用cuda114,不同的版…...
【Flink】Flink 处理函数之基本处理函数(一)
1. 处理函数介绍 流处理API,无论是基本的转换、聚合、还是复杂的窗口操作,都是基于DataStream进行转换的,所以统称为DataStreamAPI,这是Flink编程的核心。 但其实Flink为了更强大的表现力和易用性,Flink本身提供了多…...
【Java - 框架 - Lombok】(2) SpringBoot整合Lombok完成日志的创建使用 - 快速上手;
"SpringBoot"整合"Lombok"完成日志的创建使用 - 快速上手; 环境 “Java"版本"1.8.0_202”;“Lombok"版本"1.18.20”;“Spring Boot"版本"2.5.9”;“Windows 11 专业版_22621…...
linux 系统安装php 8.0.2
1. 安装包准备 https://www.php.net/distributions/php-8.0.22.tar.gz 我下载到 /usr/local/src 这个目录了 cd /usr/local/srcwget https://www.php.net/distributions/php-8.0.22.tar.gz 2. tar 解压 然后进到解压的文件夹 tar -zxvf php-8.0.22.tar.gz cd php-8.0.2…...
你管这破玩意叫网络
你是一台电脑,你的名字叫 A 很久很久之前,你不与任何其他电脑相连接,孤苦伶仃。 直到有一天,你希望与另一台电脑 B 建立通信,于是你们各开了一个网口,用一根网线连接了起来。 用一根网线连接起来怎么就能…...
系统开发实训小组作业week5 —— 用例描述与分析
目录 1、电影管理 1.1、 用例描述 1.2、 活动图 1.3、 界面元素 1.4、 功能 2、用户管理 2.1、 用例描述 2.2、 活动图 2.3、 界面元素 2.4、 功能 1、电影管理 1.1、 用例描述 用例号 UC009-01 用例名称 电影管理 用例描述 管理员实现对电影信息、座位数量、价…...
C语言例4-35:鸡翁一,值钱五;鸡母一,值钱三;鸡雏三,值钱一。百钱买百鸡、问鸡翁、鸡母和鸡雏各几何?
方法一: 代码如下: //鸡翁一,值钱五;鸡母一,值钱三;鸡雏三,值钱一。百钱买百鸡、问鸡翁、鸡母和鸡雏各几何? //方法一: #include<stdio.h> int main(void) {int x…...
Leetcode 167. 两数之和 II - 输入有序数组
给你一个下标从 1 开始的整数数组 numbers ,该数组已按 非递减顺序排列 ,请你从数组中找出满足相加之和等于目标数 target 的两个数。如果设这两个数分别是 numbers[index1] 和 numbers[index2] ,则 1 < index1 < index2 < numbers.…...
Java实体类之间的转换
一.为什么要转换实体类 通常在后端开发中经常不直接返回实体Entity类,经过处理转换返回前端,前端提交过来的对象也需要经过转换Entity实体才做存储。 二.怎么转换 使用的BeanUtils.copyProperties方法虽然可以实现转换,但是比较粗暴&#…...
ESCTF-Web赛题WP
0x01-初次见面-怦然心动:your name? 随便输入一个字 根据提示可以看到 我们需要看源代码 直接 搜索 secret 关键字或者 ESCTF flag ESCTF{K1t0_iS_S0_HAPPy} 0x02-小k的请求 更安全的传参 post 参数为ESCTF 值为 love 自己的ip 同时还有个要求 是需要从度娘转过来 https://www…...
某物登录表单加密
之前分析过某物h5的以及小程序的搜索接口,就是一个aes,秘钥不固定,表单里把秘钥以及密文一起发过去,服务器解密后再把数据加密返回,客户端解密展示到页面上. 这期是关于app的登录,密码登录 声明 本文章中所有内容仅供学习交流使用,不用于其他任何目的,…...
2024java面试题
题目:反转一个单链表描述:给定一个单链表的头节点,将其反转,返回反转后的链表的头节点。 题目:合并两个有序链表描述:给定两个有序链表的头节点,将它们合并成一个有序链表,返回合并…...
FebHost:什么是哈萨克斯坦.KZ域名?
哈萨克斯坦,作为中亚地区重要的一员,其国家域名”.kz”正成为这个独立国家在网络世界中的代表。作为一个经济快速发展的国家,哈萨克斯坦的互联网基础设施和网络应用也在蓬勃发展。而.kz域名正是哈萨克斯坦网络身份的重要体现。 作为注册和管理.kz域名的主要机构,哈…...
python(一)网络爬取
在爬取网页信息时,需要注意网页爬虫规范文件robots.txt eg:csdn的爬虫规范文件 csdn.net/robots.txt User-agent: 下面的Disallow规则适用于所有爬虫(即所有用户代理)。星号*是一个通配符,表示“所有”。 Disallow&…...
港大新工作 HiGPT:一个模型,任意关系类型 !
论文标题: HiGPT: Heterogeneous Graph Language Model 论文链接: https://arxiv.org/abs/2402.16024 代码链接: https://github.com/HKUDS/HiGPT 项目网站: https://higpt-hku.github.io/ 1. 导读 异质图在各种领域…...
Git版本管理使用手册 - 5 - Git的.ignore文件语法
Git的.ignore文件 1.使用 .ignore文件可以忽略指定文件的版本控制。 2.语法: (1)#开头表示注释 (2)!开头表示不忽略匹配文件 (3)* 表示除/外,任何字符串 (4)?表示除/外,任何一个字符 (5)/ 如果模式的结尾有分割符/&am…...
使用Spring Cloud Gateway构建API网关,实现路由、过滤、流量控制等功能。
使用Spring Cloud Gateway构建API网关,实现路由、过滤、流量控制等功能。 使用Spring Cloud Gateway可以轻松地构建API网关,实现路由、过滤、流量控制等功能。下面是一个简单的示例,演示如何在Spring Boot应用程序中集成Spring Cloud Gatewa…...
Matlab|电动汽车充放电V2G模型
目录 1 主要内容 1.1 模型背景 1.2 目标函数 1.3 约束条件 2 部分代码 3 效果图 4 下载链接 1 主要内容 本程序主要建立电动汽车充放电V2G模型,采用粒子群算法,在保证电动汽车用户出行需求的前提下,为了使工作区域电动汽车尽可能多的消…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...
stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...
循环冗余码校验CRC码 算法步骤+详细实例计算
通信过程:(白话解释) 我们将原始待发送的消息称为 M M M,依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)(意思就是 G ( x ) G(x) G(x) 是已知的)࿰…...
STM32+rt-thread判断是否联网
一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
c#开发AI模型对话
AI模型 前面已经介绍了一般AI模型本地部署,直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型,但是目前国内可能使用不多,至少实践例子很少看见。开发训练模型就不介绍了&am…...
Android15默认授权浮窗权限
我们经常有那种需求,客户需要定制的apk集成在ROM中,并且默认授予其【显示在其他应用的上层】权限,也就是我们常说的浮窗权限,那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...
【JavaSE】绘图与事件入门学习笔记
-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...
DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”
目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...
