模板方法模式(继承的优雅使用)

news2024/11/17 5:41:58

目录

前言

UML

plantuml

类图

实战代码

AbstractRoutingDataSource

DynamicDataSource

DynamicDataSourceContextHolder


前言

在设计类时,一般优先考虑使用组合来替代继承,能够让程序更加的灵活,但这并不意味着要完全抛弃掉继承。

继承在面向对象编程中用来减少代码冗余和提高复用性,是面向对象编程的一大特性。

只不过在使用继承时必须满足一些条件,才能让我们更好地利用继承,设计出更易维护和扩展的程序。

一般情况下,使用继承需要满足一下两个条件

  1. 父类所有的属性和方法,都能在子类中适用
  2. 子类无需复用其他类的方法,并且不会覆写父类已有的方法

模板方法模式是继承使用的优雅示例,一般会设计一个抽象类,在类中定义了一个操作的算法结构,其中一些步骤被设计为抽象方法,需要子类去实现,这些方法被称为模板方法。

模板方法允许子类在不改变算法结构的情况下,重新定义算法的某些特定步骤。

UML

plantuml

@startuml
'https://plantuml.com/class-diagram

abstract Template {
    + doSomething() : void
    - step1() : void
    - step2() : void
    + {abstract} step3() : void
}

class Concrete {
    + step3() : void
}

class Client {}

Template <|-- Concrete

Client ..> 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();
    }

    @Override
    protected 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();
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL高级SQL2

一、表连接 二、视图 三、null值和空值区别 四、存储过程 五、函数 六、字符串函数 七、日期时间函数

迅雷拉新关键词怎么申请?

在这个日新月异、竞争激烈的时代&#xff0c;网盘项目的寻找与对接已成为众多团队谋求突破的关键。那么&#xff0c;如何在茫茫项目海中筛选出既靠谱又有潜力的明珠呢&#xff1f;经过深度挖掘和全网搜索&#xff0c;我为大家精心整理了优质接单渠道&#xff0c;助力网盘拉新团…

大模型prompt工程学习(一)

目录 调prompt的方法 prompt时好时不好 大模型本质是没有记忆的 划重点:我们发给大模型的 prompt&#xff0c;不会改变大模型的参数 ГLets think step by step」 一步步分析一下 自洽性&#xff0c;同时跑多次&#xff0c;来减少幻觉 逻辑&#xff0c;基本能力来是要有…

Android卡顿掉帧问题分析之实战篇

本文将结合典型实战案例&#xff0c;分析常见的造成卡顿等性能问题的原因。从系统工程师的总体角度来看 &#xff0c;造成卡顿等性能问题的原因总体上大致分为三个大类&#xff1a;一类是流程执行异常&#xff1b;二是系统负载异常&#xff1b;三是编译问题引起。 1 流程执行异…

web全栈架构师第16期教程

教程介绍 互联网时代已进入后半场&#xff0c;行业环境发生了显著变化。互联网人&#xff0c;尤其是技术人员&#xff0c;如何在加速更迭的技术浪潮中持续充电&#xff0c;提升自身价值&#xff0c;是当下必须面对的挑战。课程涉及了现下前端实际开发时所需要的各块内容&#…

Java Web-HTTP协议

概念: Hyper Text Transfer Protocol,超文本传输协议,规定了浏览器和服务器之间数据传输的规则。 特点: 1.基于TCP协议:面向连接,安全 2. 基于请求-响应模型的:一次请求对应一次响应 3. HTTP协议是无状态的协议:对于事务处理没有记忆能力。每次请求-响应都是独立的。 缺点:多…

MBR4060DC-ASEMI肖特基二极管MBR4060DC

编辑&#xff1a;ll MBR4060DC-ASEMI肖特基二极管MBR4060DC 型号&#xff1a;MBR4060DC 品牌&#xff1a;ASEMI 封装&#xff1a;TO-263 最大平均正向电流&#xff08;IF&#xff09;&#xff1a;40A 最大循环峰值反向电压&#xff08;VRRM&#xff09;&#xff1a;60V …

小红的炸砖块

题目描述 小红正在玩一个“炸砖块”游戏&#xff0c;游戏的规则如下&#xff1a; 初始有一个n∗m的砖块矩阵。小红会炸k次&#xff0c;每次会向一个位置投炸弹&#xff0c;如果这个位置有一个砖块&#xff0c;则砖块消失&#xff0c;上方的砖块向下落。 小红希望你画出最终砖块…

Android Studio Iguana | 2023.2.1 补丁 1

Android Studio Iguana | 2023.2.1 Canary 3 已修复的问题Android Gradle 插件 问题 295205663 将 AGP 从 8.0.2 更新到 8.1.0 后&#xff0c;任务“:app:mergeReleaseClasses”执行失败 问题 298008231 [Gradle 8.4][升级] 由于使用 kotlin gradle 插件中已废弃的功能&#…

程序员也写歌啦

我的第一首AI原创歌曲《旅途的歌声》 身为 AI 重度患者的我&#xff0c;时刻关注着每天发布的各种 AI 产品。面对这些雨后春笋般的 AI 产品&#xff0c;我也早就没那么敏感了。 但是今天尝试着用 AI 生成了一个音乐&#xff0c;真的震惊到了我&#xff01; 不到一分钟&#…

2024年第六届机器人系统与自动化工程国际会议(RSAE 2024)即将召开!

2024年第六届机器人系统与自动化工程国际会议&#xff08;RSAE 2024&#xff09;将于2024年6月21-23日在日本东京召开。RSAE 2024 的主要目标是加强合作&#xff0c;并为院士、专业人士和研究人员提供一个论坛&#xff0c;交流他们的研究成果、创新理念和解决方案&#xff0c;包…

算法打卡day29|贪心算法篇03|Leetcode 1005.K次取反后最大化的数组和、134. 加油站、135. 分发糖果

算法题 Leetcode 1005.K次取反后最大化的数组和 题目链接:1005.K次取反后最大化的数组和 大佬视频讲解&#xff1a;K次取反后最大化的数组和视频讲解 个人思路 思路清晰&#xff0c;因为是取反当然是取越小的负数越好&#xff0c;那么先按绝对值排序。如果是负数就取反&#…

Tomcat 下载以及安装

Tomcat安装及配置教程主要分为四步&#xff1a; 步骤一&#xff1a;首先确认自己是否已经安装JDK 1. cmd&#xff1a;查看java的版本 步骤二&#xff1a;下载安装Tomcat 1. 下载tomcat :Apache Tomcat - Welcome! 2. 选择对应的tomcat版本&#xff1a; 3. 进行安装&#…

左值引用、右值引用及移动语义

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 左值 概念 可以取到地址的值就是左值&#xff0c;并且一般情况下可以修改&#xff08;const类型左值不可修改&#xff09;。 左值举例&#xff1a; //左值 int a 0; const int b 1; int* p &a; 右值 概念 不能…

虚拟ECU:汽车空调压缩机控制系统

2024年是“十四五”的“关键一年”&#xff0c;在中国居民生活水平不断上升的趋势下&#xff0c;人们对汽车的需求已不再局限于简单的代步工具&#xff0c;而对其整体的舒适度和体验度也有着越来越高的要求。作为提升驾车与乘车体验的重要部分&#xff0c;汽车的空调系统在电动…

3D软件坐标系速查

本文介绍不同3D软件的世界坐标系之间的差异及其工作原理。 基本上&#xff0c;游戏引擎和3D软件包最重要的问题是根据软件的坐标轴系统创建资产&#xff0c;正确缩放它们并根据要完成的工作设置枢轴系统。 坐标系正确性的定义可能会根据模型导入的游戏引擎或 3D 软件而变化。…

Python Flask-Mail实现邮件发送

一、邮件发送的扩展 关于如何找到flask发送邮件的插件&#xff1f;&#xff0c;上一篇已经分享了如何找到第三方插件&#xff0c;也找到了插件flask-mail的使用文档&#xff0c;那我们就来实战吧 二、根据文档&#xff0c;总结发送邮件的流程 从文档中可以总结出发送邮件的步…

【JavaScript】JavaScript 程序流程控制 ⑦ ( do-while 循环概念 | do-while 循环语法结构 )

文章目录 一、while 循环1、while 循环概念2、do-while 循环语法结构 二、do-while 循环代码示例1、打印 1-5 数字2、打印 1-10 累加和 一、while 循环 1、while 循环概念 JavaScript 中的 do-while 循环 是 while 循环的变体 , 是 一种 后测试 循环 , 该循环的 循环体 至少执行…

Lazada、shopee自养号测评环境搭建需要准备哪些?

在如今电商竞争日益激烈的环境下&#xff0c;卖家们深知流量对店铺转化率的至关重要性。依赖平台内部的流量已不再足够&#xff0c;越来越多的卖家开始探索其他方式来提升销售业绩和品牌知名度。其中&#xff0c;自养号测评成为了一种备受关注的策略&#xff0c;通过搭建独立运…

零基础自学C语言|文件操作

✈为什么使用文件&#xff1f; 如果没有文件&#xff0c;我们写的程序的数据是存储在电脑的内存中&#xff0c;如果程序退出&#xff0c;内存回收&#xff0c;数据就丢失了&#xff0c;等再次运行程序&#xff0c;是看不到上次程序的数据的&#xff0c;如果要将数据进行持久化…