模板方法模式详解
模板方法模式(行为模式)
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 滚动信息…...
Python|GIF 解析与构建(5):手搓截屏和帧率控制
目录 Python|GIF 解析与构建(5):手搓截屏和帧率控制 一、引言 二、技术实现:手搓截屏模块 2.1 核心原理 2.2 代码解析:ScreenshotData类 2.2.1 截图函数:capture_screen 三、技术实现&…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...
YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...
select、poll、epoll 与 Reactor 模式
在高并发网络编程领域,高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表,以及基于它们实现的 Reactor 模式,为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。 一、I…...
如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...
iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈
在日常iOS开发过程中,性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期,开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发,但背后往往隐藏着系统资源调度不当…...
