模板方法模式详解
模板方法模式(行为模式)
1. 模板方法模式介绍
- 父类定义算法骨架,细节的具体实现延迟到子类
- 子类只是定义某些自己的个性化处理,但不改变执行顺序
2. 好处
- 减少代码冗余,共性抽取后算法流程更加清晰与规范
- 降低流程性错误的可能,开发类似的新需求,能通过父类算法骨架清晰理出流程
- 定义了统一执行标准,便于管理与控制流程
- 子类仅需要实现自己的个性化业务,修改自己的业务不会影响其他业务,符合单一职责原则
3. 场景案例
- 项目中会开发大量实时变化的榜单,榜单的更新与查询流程基本都相同,如:公共校验、个性化校验、榜单排名获取、符合规则上榜、不符合规则下榜,但不同榜单校验方式与获取渠道不同
- 使用模板方法模式
- 接口添加为需要的抽象方法
- 抽象类实现接口添加算法骨架与实现统一的抽象方法,同时使用接口的抽象方法
- 具体的榜单需要继承抽象父类,实现抽象方法,然后调用算法骨架方法即可
- 一对一视频聊有三中场景,执行流程均相同,但是计费规则等业务不同
- 抽象父类定义执行顺序
- 三种场景:一对一、直播转向、速配,直接继承父类处理规则,然后实现自己具体的计费规则
4. 案例源码
- 代码结构
├── IRank.java
├── base
│ └── AbstractBaseRank.java
├── bean
│ ├── RankDelReq.java
│ └── RankMessageReq.java
├── ext
│ └── ExtServiceImpl.java
└── impl└── RankServiceImpl.java
- 公共榜单接口
public interface IRank {/*** 公用判断,是否被审核处罚等处理,返回判断结果* @return {@code 0} 正常、不用下榜(也可使用 Enum 枚举)*/int getCommLimit(long userId);/*** 个性化判断,返回判断结果* @return {@code 0} 正常、不用下榜(也可使用 Enum 枚举)*/int getRankUp(long userId);/*** 查询用户在榜单的分数* @return 返回分数 Redis 中 zset 数据结构的 score* {@code null} 分数为 null 需要下榜单,*/Double getScore(long userId);/*** 用户上榜* @return {@code true} 用户上榜成功*/boolean doRankUp(RankDelReq rankDelReq);/*** 用户下榜* @return {@code true} 用户下榜成功*/boolean doRankDown(RankDelReq rankDelReq);
}
- 公共榜单抽象父类
- 定义算法骨架,实现公共的方法
public abstract class AbstractBaseRank implements IRank {/*** 榜单处理流程*/public void dealRank(RankMessageReq rankMessage) {// 判空if (rankMessage == null || rankMessage.getUserId() == null) {System.out.println(String.format("传入信息异常:%s", rankMessage));return;}long userId = rankMessage.getUserId();// 公共判断int commLimit = getCommLimit(userId);// 不符合则下榜if (commLimit != 0) {boolean rankDownFlag = doRankDown(new RankDelReq(userId, null, commLimit));System.out.println(String.format("用户:%s 不符合公共判断下榜单:%s 下榜结果:%s", userId, commLimit, rankDownFlag));return;}// 个性化判断int rankUpLimit = getRankUp(userId);// 不符合则下榜if (rankUpLimit != 0) {boolean rankDownFlag = doRankDown(new RankDelReq(userId, null, rankUpLimit));System.out.println(String.format("用户:%s 不符合个性化判断下榜单:%s 下榜结果:%s", userId, rankUpLimit, rankDownFlag));return;}// 返回分数Double score = getScore(userId);// 分数为 null 则下榜if (score == null) {boolean rankDownFlag = doRankDown(new RankDelReq(userId, score, null));System.out.println(String.format("用户:%s 没有分数判断下榜单 下榜结果:%s", userId, rankDownFlag));return;}boolean rankUpFlag = doRankUp(new RankDelReq(userId, score, null));System.out.println(String.format("用户:%s 上榜结果:%s", userId, rankUpFlag));}/*** 公用判断,是否被审核处罚等处理,返回判断结果* @return {@code 0} 正常、不用下榜(也可使用 Enum 枚举)*/@Overridepublic int getCommLimit(long userId) {// 被冻结if (ExtServiceImpl.isFreeze(userId)) {System.out.println(String.format("用户:%s 被冻结:%s", userId));return 1;}// 被禁玩if (ExtServiceImpl.isBan(userId)) {System.out.println(String.format("被禁玩:%s", userId));return 2;}// 榜单审核中if (ExtServiceImpl.isRankAudit(userId)) {System.out.println(String.format("榜单审核中:%s", userId));return 3;}return 0;}
}
- 具体某个榜单实现类
public class RankServiceImpl extends AbstractBaseRank {/*** 个性化判断,返回判断结果* @return {@code 0} 正常、不用下榜(也可使用 Enum 枚举)*/@Overridepublic int getRankUp(long userId) {System.out.println("个性化判断");return 0;}/*** 查询用户在榜单的分数* @return 返回分数 Redis 中 zset 数据结构的 score* {@code null} 分数为 null 需要下榜单,*/@Overridepublic Double getScore(long userId) {System.out.println("查询用户在榜单的分数");return 0D;}/*** 用户上榜* @return {@code true} 用户上榜成功*/@Overridepublic boolean doRankUp(RankDelReq rankDelReq) {System.out.println("用户上榜");return true;}/*** 用户下榜* @return {@code true} 用户下榜成功*/@Overridepublic boolean doRankDown(RankDelReq rankDelReq) {System.out.println("用户下榜");return true;}
}
- 单元测试代码
public class RankServiceImplTest {@Testpublic void test() {RankServiceImpl rankServiceImpl = new RankServiceImpl();System.out.println(String.format("用户:%s 榜单处理", 2808253L));rankServiceImpl.dealRank(new RankMessageReq(2808253L));System.out.println();System.out.println(String.format("用户:%s 榜单处理", null));rankServiceImpl.dealRank(new RankMessageReq(null));}
}
相关文章:
模板方法模式详解
模板方法模式(行为模式) 1. 模板方法模式介绍 父类定义算法骨架,细节的具体实现延迟到子类子类只是定义某些自己的个性化处理,但不改变执行顺序 2. 好处 减少代码冗余,共性抽取后算法流程更加清晰与规范降低流程性…...
关于 Lightweight process container,ChatGPT的答案
晓楚 Can you give me a list of process container? As an AI language model, I can provide you with a list of popular process containers, which are as follows: Docker Kubernetes Apache Mesos LXC OpenVZ systemd-nspawn rkt (Rocket) Linux Containers (LXC) Ga…...
机器学习和深度学习的综述
机器学习和深度学习的综述 1.1.1人工智能、机器学习、深度学习的关系 人工智能(Artificial Intelligence,AI)是最宽泛的概念,是研发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门新的技术科学。由于这个定义…...
Synopsys Sentaurus TCAD系列教程之--Sprocess(SmallMOS_2D3D) 解析
SmallMOS_2D3D解析 #header## STI depth set sti_depth 0.15 ## Half STI width set sti_width sti_width ## Half gate length set gate_len <lg/2> ## SD length (from center) set sd_len [expr $gate_len0.05]#endheader## X lines line x location 0.0 spacing 0.…...
好使!NAS中傻瓜式配置反向代理及SSL证书,提升网络安全性!
对于有NAS或者有个人主机的朋友来说,将机器映射到外网是基本操作。 但是一般来说,能直接从外网访问的往往仅有80和443端口。事实上,运营商一般把家庭宽带的这两个端口都封了,所以如果我们想要从外网访问自己家中机器部署的服务&a…...
数据结构队列-先进先出
一,概述 队列这个概念非常好理解。你可以把它想象成排队买票,先来的先买,后来的人只能站末尾,不允许插队。先进者先出,这就是典型的“队列”。 二,顺序队列和链式队列 队列和栈一样,也是一种…...
CentOS 7使用TiUP部署TiDB
本文主要是根据官方文档指导,结合实际主机情况,在Cent OS7上使用TiUP在线部署TiDB。 环境说明 类型操作系统版本配置中控机Deepin 20.34核CPU6G内存40G硬盘TiDB部署机Cent OS 7.38核CPU48G内存100硬盘网络情况中控机与外网相连,中控机与部署…...
java单元测试批处理数据模板【亿点点日志配合分页以及多线程处理】
文章目录引入相关资料环境准备分页查询处理,减少单次批量处理的数据量级补充亿点点日志,更易观察多线程优化查询_切数据版多线程_每个线程都分页处理引入 都说后端开发能顶半个运维,我们经常需要对大量输出进行需求调整,很多时候…...
【数据结构】模拟实现 堆
堆数据结构是一种数组对象,它可以被看作一颗完全二叉树的结构(数组是完全二叉树),堆是一种静态结构。堆分为最大堆和最小堆。最大堆:每个父结点都大于孩子结点。最小堆:每个父结点都小于孩子结点。堆的优势…...
Go语言学习的第三天--上部分(基础用法)
前两天经过不断度娘,与对up主的跟踪学习了解了go的历史,今天开始了go的基础!!本章主要是go 的注释、变量及常量的梳理一、注释不管什么语言都有自己的注释,go也不例外 !!单行注释 // 多行注释 …...
linux面试基础篇
题目目录1.简述DNS分离解析的工作原理,关键配置2.apache有几种工作模式,分别简述两种工作模式及其优缺点?3.写出172.0.0.38/27 的网络id与广播地址4.写出下列服务使用的传输层协议(TCP/UDP)及默认端口5.在局域网想获得…...
黑马程序员提高变成
这里写目录标题函数模板1.2.2 函数模板注意事项1.2.3 函数模板案例调用规则类模板与函数模板区别类模板与继承类模板成员函数类外实现#pragma once类模板与友元案例重新定义【】stl2.2 STL基本概念STL六大组件容器算法迭代器初识vectorvector容器嵌套容器string容器string赋值操…...
MySQL5种索引类型
MySQL的类型主要有五种:主键索引、唯一索引、普通索引、空间索引、全文索引 有表: CREATE TABLE t1 ( id bigint unsigned NOT NULL AUTO_INCREMENT, u1 int unsigned NOT NULL DEFAULT 0, u2 int unsigned NOT NULL DEFAULT 0, u3 varchar(20) NOT NU…...
uniapp封装缓存方法,支持类似cookie具有过期时间
1、定义CacheManage类,有set和get方法 class CacheManage {set() {},get() {} }set用来设置缓存,get用来获取缓存 2、完善set业务逻辑 大概逻辑如下: 1、将接收params参数,包含key、data、unit、time key 缓存字段,…...
Jfrog 搭建本地maven仓库以及上传Android库
Jfrog 下载 安装包下载地址:Download Artifactory OSS | JFrog 如果是想下载之前的版本,可以点击上面的Get code source ,如果是最新版本,直接点下面的下载就好。下面以Linux安装为例。 Jfrog安装 对于Linux而言,其实…...
日报周报月报工作总结生成器【智能文案生成器】
日报周报月报工作总结生成器【智能文案生成器】 天天写日报,我真的快奔溃了! 摸了一天鱼,下班还要写日报; 划了一周的水,周末还要写周报; 啊啊啊啊… 在职场上,尤其是互联网公司里,…...
linux日志管理工具logrotate配置
linux日志管理工具logrotate配置logrotate介绍logrotate配置讲解主配置文件解释(/etc/logrotate.conf)logrotete 命令参数添加配置以添加一个nginx配置为例强制启动配置logrotate介绍 logrotate是centos自带工具,其他操作系统可能需要自行安装。logrotate用来进行日…...
[ C++ ] 设计模式——单例模式
目录 1.设计模式: 2.单例模式 饿汉模式 懒汉模式 饿汉模式和懒汉模式的优缺点 1.设计模式: 设计模式(Design Pattern)是一套被反复使用,多数人只晓得,经过分类的,代码设计经验的总结。为什么会产生设计模式这样的…...
HACKTHEBOX——Help
nmap可以看到对外开放了22,80,3000端口可以看到80端口和3000端口都运行着http服务,先从web着手切入TCP/80访问web提示无法连接help.htb,在/etc/hosts中写入IP与域名的映射打开只是一个apache default页面,没什么好看的使用gobuster扫描网站目…...
Qt广告机客户端(下位机)
目录功能结构adClient.promain.cppadclient.h 客户端adclient.cpp 客户端addate.h 时间处理addate.cpp 时间处理adsocket.h 客户端Socket处理adsocket.cpp 客户端Socket处理weather.h 天气信息处理weather.cpp 天气信息处理rollmassege.h 滚动信息处理rollmassege.cpp 滚动信息…...
Xshell远程连接Kali(默认 | 私钥)Note版
前言:xshell远程连接,私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...
通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...
sqlserver 根据指定字符 解析拼接字符串
DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...
《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...
