当前位置: 首页 > news >正文

模板方法模式详解

模板方法模式(行为模式)

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或者有个人主机的朋友来说&#xff0c;将机器映射到外网是基本操作。 但是一般来说&#xff0c;能直接从外网访问的往往仅有80和443端口。事实上&#xff0c;运营商一般把家庭宽带的这两个端口都封了&#xff0c;所以如果我们想要从外网访问自己家中机器部署的服务&a…...

数据结构队列-先进先出

一&#xff0c;概述 队列这个概念非常好理解。你可以把它想象成排队买票&#xff0c;先来的先买&#xff0c;后来的人只能站末尾&#xff0c;不允许插队。先进者先出&#xff0c;这就是典型的“队列”。 二&#xff0c;顺序队列和链式队列 队列和栈一样&#xff0c;也是一种…...

CentOS 7使用TiUP部署TiDB

本文主要是根据官方文档指导&#xff0c;结合实际主机情况&#xff0c;在Cent OS7上使用TiUP在线部署TiDB。 环境说明 类型操作系统版本配置中控机Deepin 20.34核CPU6G内存40G硬盘TiDB部署机Cent OS 7.38核CPU48G内存100硬盘网络情况中控机与外网相连&#xff0c;中控机与部署…...

java单元测试批处理数据模板【亿点点日志配合分页以及多线程处理】

文章目录引入相关资料环境准备分页查询处理&#xff0c;减少单次批量处理的数据量级补充亿点点日志&#xff0c;更易观察多线程优化查询_切数据版多线程_每个线程都分页处理引入 都说后端开发能顶半个运维&#xff0c;我们经常需要对大量输出进行需求调整&#xff0c;很多时候…...

【数据结构】模拟实现 堆

堆数据结构是一种数组对象&#xff0c;它可以被看作一颗完全二叉树的结构&#xff08;数组是完全二叉树&#xff09;&#xff0c;堆是一种静态结构。堆分为最大堆和最小堆。最大堆&#xff1a;每个父结点都大于孩子结点。最小堆&#xff1a;每个父结点都小于孩子结点。堆的优势…...

Go语言学习的第三天--上部分(基础用法)

前两天经过不断度娘&#xff0c;与对up主的跟踪学习了解了go的历史&#xff0c;今天开始了go的基础&#xff01;&#xff01;本章主要是go 的注释、变量及常量的梳理一、注释不管什么语言都有自己的注释&#xff0c;go也不例外 &#xff01;&#xff01;单行注释 // 多行注释 …...

linux面试基础篇

题目目录1.简述DNS分离解析的工作原理&#xff0c;关键配置2.apache有几种工作模式&#xff0c;分别简述两种工作模式及其优缺点&#xff1f;3.写出172.0.0.38/27 的网络id与广播地址4.写出下列服务使用的传输层协议&#xff08;TCP/UDP&#xff09;及默认端口5.在局域网想获得…...

黑马程序员提高变成

这里写目录标题函数模板1.2.2 函数模板注意事项1.2.3 函数模板案例调用规则类模板与函数模板区别类模板与继承类模板成员函数类外实现#pragma once类模板与友元案例重新定义【】stl2.2 STL基本概念STL六大组件容器算法迭代器初识vectorvector容器嵌套容器string容器string赋值操…...

MySQL5种索引类型

MySQL的类型主要有五种&#xff1a;主键索引、唯一索引、普通索引、空间索引、全文索引 有表&#xff1a; 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类&#xff0c;有set和get方法 class CacheManage {set() {},get() {} }set用来设置缓存&#xff0c;get用来获取缓存 2、完善set业务逻辑 大概逻辑如下&#xff1a; 1、将接收params参数&#xff0c;包含key、data、unit、time key 缓存字段&#xff0c;…...

Jfrog 搭建本地maven仓库以及上传Android库

Jfrog 下载 安装包下载地址&#xff1a;Download Artifactory OSS | JFrog 如果是想下载之前的版本&#xff0c;可以点击上面的Get code source &#xff0c;如果是最新版本&#xff0c;直接点下面的下载就好。下面以Linux安装为例。 Jfrog安装 对于Linux而言&#xff0c;其实…...

日报周报月报工作总结生成器【智能文案生成器】

日报周报月报工作总结生成器【智能文案生成器】 天天写日报&#xff0c;我真的快奔溃了&#xff01; 摸了一天鱼&#xff0c;下班还要写日报&#xff1b; 划了一周的水&#xff0c;周末还要写周报&#xff1b; 啊啊啊啊… 在职场上&#xff0c;尤其是互联网公司里&#xff0c…...

linux日志管理工具logrotate配置

linux日志管理工具logrotate配置logrotate介绍logrotate配置讲解主配置文件解释(/etc/logrotate.conf)logrotete 命令参数添加配置以添加一个nginx配置为例强制启动配置logrotate介绍 logrotate是centos自带工具&#xff0c;其他操作系统可能需要自行安装。logrotate用来进行日…...

[ C++ ] 设计模式——单例模式

目录 1.设计模式&#xff1a; 2.单例模式 饿汉模式 懒汉模式 饿汉模式和懒汉模式的优缺点 1.设计模式&#xff1a; 设计模式(Design Pattern)是一套被反复使用&#xff0c;多数人只晓得&#xff0c;经过分类的&#xff0c;代码设计经验的总结。为什么会产生设计模式这样的…...

HACKTHEBOX——Help

nmap可以看到对外开放了22,80,3000端口可以看到80端口和3000端口都运行着http服务&#xff0c;先从web着手切入TCP/80访问web提示无法连接help.htb&#xff0c;在/etc/hosts中写入IP与域名的映射打开只是一个apache default页面&#xff0c;没什么好看的使用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 滚动信息…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!

5月28日&#xff0c;中天合创屋面分布式光伏发电项目顺利并网发电&#xff0c;该项目位于内蒙古自治区鄂尔多斯市乌审旗&#xff0c;项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站&#xff0c;总装机容量为9.96MWp。 项目投运后&#xff0c;每年可节约标煤3670…...

Spring Boot面试题精选汇总

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...

用docker来安装部署freeswitch记录

今天刚才测试一个callcenter的项目&#xff0c;所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...

MySQL用户和授权

开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务&#xff1a; test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...

Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?

Redis 的发布订阅&#xff08;Pub/Sub&#xff09;模式与专业的 MQ&#xff08;Message Queue&#xff09;如 Kafka、RabbitMQ 进行比较&#xff0c;核心的权衡点在于&#xff1a;简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...

Yolov8 目标检测蒸馏学习记录

yolov8系列模型蒸馏基本流程&#xff0c;代码下载&#xff1a;这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中&#xff0c;**知识蒸馏&#xff08;Knowledge Distillation&#xff09;**被广泛应用&#xff0c;作为提升模型…...

CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝

目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为&#xff1a;一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...

【 java 虚拟机知识 第一篇 】

目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...

作为测试我们应该关注redis哪些方面

1、功能测试 数据结构操作&#xff1a;验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化&#xff1a;测试aof和aof持久化机制&#xff0c;确保数据在开启后正确恢复。 事务&#xff1a;检查事务的原子性和回滚机制。 发布订阅&#xff1a;确保消息正确传递。 2、性…...