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

java设计模式之:策略模式+工厂模式整合案例实战(一)

本文介绍项目中常用的策略模式+工厂模式的案例,该案例是针对策略类比较少的情况下一篇会讲解策略类比较多的案例,下面直接开始:

案例1:项目中对系统中的客户和销售进行事件通知(短信、邮件、钉钉)

首先要有通知的策略接口,接口里面要有一个方法就是通知的方法

public interface PushChannelStrategy{// 通知方法SendResult send(MessagePushParam param,BaseMsg baseMsg);}

有了接口那必然有实现类,三个实现类短信、邮件、钉钉

短信:

@Slf4j
@Component
public class SmsPushChannelStrategy implements PushChannelStrategy{@Autowiredprivate NoticeClient noticeClient;@Overridepublic SendResult send(MessagePushParam param,BaseMsg baseMsg){//1、before send check//2、send smsNoticeResult noticeResult=noticeClient.sendSms(xxxx);sendResult.setMessageStatus(MessageStatusEnum.SUCCESS);return sendResult;}
}

邮件:

@Slf4j
@Component
public class EmailPushChannelStrategy implements PushChannelStrategy{@Autowiredprivate NoticeClient noticeClient;@Overridepublic SendResult send(MessagePushParam param,BaseMsg baseMsg){//1、before send check//2、send emailEmail emailMsg=(Email)baseMsg;NoticeResult noticeResult=noticeClient.sendEmail(xxxx);sendResult.setMessageStatus(MessageStatusEnum.SUCCESS);return sendResult;}
}

钉钉:

@Slf4j
@Component
public class DingTalkPushChannelStrategy implements PushChannelStrategy{@Autowiredprivate DingTalkClient dingTalkClient;@Overridepublic SendResult send(MessagePushParam param,BaseMsg baseMsg){//1、before send check//2、send ding talkSendResult sendResult=dingTalkClient.send(xxx);// 其他结果参数组装return sendResult;}
}

然后通过策略工厂来获取具体的策略类:(由于只有三个策略类,所以通过注入的方式对channel进行判断)

@Component
public class PushChannelStrategyFactory{@Autowired private DingTalkPushChannelStrategy dingTalkPushChannelStrategy;@Autowiredprivate SmsPushChannelStrategy smsPushChannelStrategy;@Autowiredprivate EmailPushChannelStrategy emailPushChannelStrategy;public PushChannelStrategy getStrategy(PushChannel pushChannel){switch(pushChannel){case DING_TALK:return dingTalkPushChannelStrategy;case SMS:return smsPushChannelStrategy;case EMAIL:return emailPushChannelStrategy;default:throw new RuntimeException("不支持的类型");}}
}

当然策略工厂针对策略实现类比较少的情况还可以这样写:

@Component
public class PushChannelStrategyFactory2{@Autowiredprivate DingTalkPushChannelStrategy dingTalkPushChannelStrategy;@Autowiredprivate SmsPushChannelStrategy smsPushChannelStrategy;@Autowiredprivate EmailPushChannelStrategy emailPushChannelStrategy;private static final Map<PushChannel,PushChannelStrategy> pushChannelBuilderMap=new HashMap<>();@PostConstructpublic void init(){pushChannelBuilderMap.put(PushChannel.SMS,smsPushChannelStrategy);pushChannelBuilderMap.put(PushChannel.Email,emailPushChannelStrategy);pushChannelBuilderMap.put(PushChannel.DING_TALK,dingTalkPushChannelStrategy);}Public PushChannelStrategy getStrategy(PushChannel PushChannel){if(PushChannel==null){return null;}return pushChannelBuilderMap.get(PushChannel);}
}

用到的枚举类:

@Getter
public enum PushChannel{SMS("sms","短信"),EMAIL("email","邮件"),DING_TALK("dingTalk","钉钉");private final String value;PushChannel(String value,String desc){this.value=value;}public static PushChannel getPushChannel(String pushChannel){if(pushChannel==null){return null;}for(PushChannel channel:PushChannel.values()){if(pushChannel.equals(channel.getValue())){return channel;}}return null;}
}

在使用的时候通过策略工厂里面的方法获取具体的策略类:

@Slf4j
@Servicepublic class MessagePushService{@Autowiredprivate PushChannelStrategyFactory pushChannelStrategyFactory;@Autowiredprivate MessageRecordRepository messageRecordRepository;public ResultDTO<Boolean> pushSync(MessagePushCommand command){MessagePushParam messagePushParam =MessagePushAssembler.convert(command);//1,业务逻辑处理//2、根据渠道进行触达PushChannel pushChannel=messagePushParam.getChannel();if(pushChannel==null){throw new MessagePushException(xxx);}//3、获取具体的策略类PushChannelStrategy pushChannelStrategy=pushChannelStrategyFactory.getStrategy(pushChannel);SendResult sendResult=PushChannelStrategy.send(messagePushParam,xxx);//4,记录落库return ResultDTO.getSuccessResult(true);}}

到此该版本的策略模式+工厂模式就结束了,欢迎点评和指出不足之处。

相关文章:

java设计模式之:策略模式+工厂模式整合案例实战(一)

本文介绍项目中常用的策略模式工厂模式的案例&#xff0c;该案例是针对策略类比较少的情况&#xff1b;下一篇会讲解策略类比较多的案例&#xff0c;下面直接开始&#xff1a; 案例1&#xff1a;项目中对系统中的客户和销售进行事件通知(短信、邮件、钉钉) 首先要有通知的策略…...

国内Ubuntu安装 stable-diffusion教程,换成国内镜像

安装依赖&#xff1a; 首先更新系统并安装Python 3.10和pip&#xff1a; sudo apt update sudo apt install python3.10 python3-pip 设置Python虚拟环境&#xff08;可选&#xff09;&#xff1a; 安装Python虚拟环境管理工具&#xff0c;并创建激活虚拟环境&#xff1a; su…...

JAVA final详细介绍

一、介绍 final 中文意思: 最后的,最终的. final 可以修饰类、属性、方法和局部变量, 在某些情况下,程序员可能有以下需求&#xff0c;就会使用到final&#xff1a; 1&#xff09;当不希望类被继承时,可以用final修饰。 //如果我们要求A类不能被其他类继承 //可以使用fin…...

45、tomcat+课后实验

tomcat 1、tomcat tomcat和php一样&#xff0c;都是用来处理动态页面的。 tomcat也可以作为web应用服务器&#xff0c;开源的。 php .php tomcat .jsp nginx .html tomcat 是用Java代码写的程序&#xff0c;运行的是Java的web应用程序。 tomcat的特点和功能&#xff1a…...

设计模式的七大原则

1.单一职责原则 单一职责原则(Single responsibility principle)&#xff0c;即一个类应该只负责一项职责。如类A负责两个不同职责&#xff1a;职责1&#xff0c;职责2。当职责1需求变更而改变A时&#xff0c;可能造成职责2执行错误&#xff0c;所以需要将类A的粒度分解为A1、…...

ThreeJS-3D教学十五:ShaderMaterial(noise、random)

ThreeJS-3D教学十四:ShaderMaterial(length、fract、step) 上面这篇主要是操作 fragmentShader 片元着色器,实现对物体颜色的修改,这次咱们来看下修改 vertexShader 顶点着色器,这个其实就是位移各个顶点的位置。 接下来我们先介绍下 noise 噪声函数(Perlin Noise、Sim…...

LeetCode 2974.最小数字游戏:排序+交换奇偶位

【LetMeFly】2974.最小数字游戏&#xff1a;排序交换奇偶位 力扣题目链接&#xff1a;https://leetcode.cn/problems/minimum-number-game/ 你有一个下标从 0 开始、长度为 偶数 的整数数组 nums &#xff0c;同时还有一个空数组 arr 。Alice 和 Bob 决定玩一个游戏&#xff…...

使用vllIm部署大语言模型

使用vllm部署大语言模型一般需要以下步骤&#xff1a; 一、准备工作 1. 系统要求 - 操作系统&#xff1a;常见的 Linux 发行版&#xff08;如 Ubuntu、CentOS&#xff09;或 Windows&#xff08;通过 WSL&#xff09;。 - GPU 支持&#xff1a;NVIDIA GPU 并安装了适当的驱动程…...

静态搜索iOS动态链接函数的调用位置

静态搜索iOS动态链接函数的调用位置 可执行文件格式mach-O,是在苹果的操作系统 macOS 和 iOS 上使用的一种二进制文件格式。 在一些iOS安全扫描中&#xff0c;可能存在需要获取函数具体调用位置的需求&#xff0c;能指导用户更精确的定位漏洞。 现在以NSLog函数为例&#xff…...

【鸿蒙学习笔记】尺寸设置・layoutWeight・对子组件进行重新布局

官方文档&#xff1a;尺寸设置 目录标题 layoutWeight&#xff1a;对子组件进行重新布局 layoutWeight&#xff1a;对子组件进行重新布局 设置了layoutWeight属性的子元素与兄弟元素占主轴尺寸按照权重进行分配&#xff0c;忽略元素本身尺寸设置。 // 引入包名 import { http…...

vue实现表单输入框数字类型校验功能

vue实现表单输入框数字类型校验功能 1. 样式代码 <el-form-item label"订单总价"><el-input size"small" v-model"form.totalPrice" placeholder"请输入订单总价 正整数或者2位数小数" input"check(form.totalPric…...

JS登录页源码 —— 可一键复制抱走

前期回顾 https://blog.csdn.net/m0_57904695/article/details/139838176?spm1001.2014.3001.5501https://blog.csdn.net/m0_57904695/article/details/139838176?spm1001.2014.3001.5501 登录页预览效果 <!DOCTYPE html> <html lang"en"><head…...

Kithara与OpenCV (一)

Kithara使用 OpenCV 库 目录 Kithara使用 OpenCV 库简介需求和支持的环境构建 OpenCV 库使用 CMake 进行配置以与 Kithara 一起工作 使用 OpenCV 库设置项目运行 OpenCV 代码图像采集和 OpenCV自动并行化限制和局限性1.系统建议2.实时限制3.不支持的功能和缺失的功能4.显示 Ope…...

什么是软件定义安全SDSec

一、软件定义安全SDSec产生的背景 软件定义安全&#xff08;Software Defined Security&#xff0c;SDSec&#xff09;的产生背景主要源于传统网络安全防护方法在面对复杂网络环境时的不适应性&#xff0c;以及软件定义网络&#xff08;SDN&#xff09;技术的发展和应用。 SD…...

【C语言】C语言可以做什么?

目录 1. 操作系统开发1.1 操作系统内核1.2 设备驱动程序1.3 系统工具和实用程序 2. 嵌入式系统2.1 微控制器编程2.2 传感器和执行器控制2.3 消费电子产品 3. 应用程序开发3.1 图形用户界面应用3.2 游戏开发3.3 多媒体处理 4. 网络编程4.1 网络协议实现4.2 服务器和客户端程序4.…...

WordPress 主题技巧:给文章页增加“谁来过”模块。

模块功能&#xff1a; 我个人目前在做一个电影类的网站&#xff0c;在开发文章页的模版时候&#xff0c;突然觉得给文章页增加一个“谁对本电影感兴趣”的功能模块可能会比较有趣&#xff0c;这个功能有点类似于‘足迹’的感觉&#xff0c;用户可以通过这个功能&#xff0c;发…...

【vue组件库搭建07】Vitest单元测试

vitest官网 vue-test-utils 我们的测试框架选择的是 Vitest 和 vue-test-utils。两者的关系为&#xff1a; Vitest 提供测试方法&#xff1a;断言、Mock 、SpyOn 等方法。vue-test-utils: 挂载和渲染组件&#xff1a; Vue Test Utils 允许您在隔离中挂载组件&#xff0c;这意…...

JSONObject和Map<String, Object>的转换

一、前言 Java开发中出参返回和入参传入更灵活的方法是使用Map<String, Object>入参或出参&#xff0c;或者使用JSONObject。 1、好处&#xff0c;参数可变&#xff0c;对接口扩展性很友好。 public ResponseData<WXModelDTO> getUserInfo(RequestBody Map<…...

C# 建造者模式(Builder Pattern)

建造者模式&#xff08;Builder Pattern&#xff09;&#xff0c;也被称为生成器模式&#xff0c;是一种对象构建模式&#xff0c;旨在将复杂对象的构建过程与表示分离&#xff0c;使得同样的构建过程可以创建不同的表示。这种模式特别适用于构建具有多个组成部分的复杂对象&am…...

初阶数据结构速成

本篇文章算是对初阶数据结构的总结&#xff0c;内容较多&#xff0c;请耐心观看 基础概念部分 顺序表 线性表&#xff08; linear list &#xff09;是n个具有相同特性的数据元素的有限序列。 线性表是⼀种在实际中⼴泛使 ⽤的数据结构&#xff0c;常⻅的线性表&#xff1a;…...

Python|GIF 解析与构建(5):手搓截屏和帧率控制

目录 Python&#xff5c;GIF 解析与构建&#xff08;5&#xff09;&#xff1a;手搓截屏和帧率控制 一、引言 二、技术实现&#xff1a;手搓截屏模块 2.1 核心原理 2.2 代码解析&#xff1a;ScreenshotData类 2.2.1 截图函数&#xff1a;capture_screen 三、技术实现&…...

手游刚开服就被攻击怎么办?如何防御DDoS?

开服初期是手游最脆弱的阶段&#xff0c;极易成为DDoS攻击的目标。一旦遭遇攻击&#xff0c;可能导致服务器瘫痪、玩家流失&#xff0c;甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案&#xff0c;帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题

分区配置 (ptab.json) img 属性介绍&#xff1a; img 属性指定分区存放的 image 名称&#xff0c;指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件&#xff0c;则以 proj_name:binary_name 格式指定文件名&#xff0c; proj_name 为工程 名&…...

Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问&#xff08;基础概念问题&#xff09; 1. 请解释Spring框架的核心容器是什么&#xff1f;它在Spring中起到什么作用&#xff1f; Spring框架的核心容器是IoC容器&#…...

Go语言多线程问题

打印零与奇偶数&#xff08;leetcode 1116&#xff09; 方法1&#xff1a;使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...

论文阅读:Matting by Generation

今天介绍一篇关于 matting 抠图的文章&#xff0c;抠图也算是计算机视觉里面非常经典的一个任务了。从早期的经典算法到如今的深度学习算法&#xff0c;已经有很多的工作和这个任务相关。这两年 diffusion 模型很火&#xff0c;大家又开始用 diffusion 模型做各种 CV 任务了&am…...

Python爬虫实战:研究Restkit库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的有价值数据。如何高效地采集这些数据并将其应用于实际业务中,成为了许多企业和开发者关注的焦点。网络爬虫技术作为一种自动化的数据采集工具,可以帮助我们从网页中提取所需的信息。而 RESTful API …...

轻量级Docker管理工具Docker Switchboard

简介 什么是 Docker Switchboard &#xff1f; Docker Switchboard 是一个轻量级的 Web 应用程序&#xff0c;用于管理 Docker 容器。它提供了一个干净、用户友好的界面来启动、停止和监控主机上运行的容器&#xff0c;使其成为本地开发、家庭实验室或小型服务器设置的理想选择…...

网页端 js 读取发票里的二维码信息(图片和PDF格式)

起因 为了实现在报销流程中&#xff0c;发票不能重用的限制&#xff0c;发票上传后&#xff0c;希望能读出发票号&#xff0c;并记录发票号已用&#xff0c;下次不再可用于报销。 基于上面的需求&#xff0c;研究了OCR 的方式和读PDF的方式&#xff0c;实际是可行的&#xff…...

比较数据迁移后MySQL数据库和ClickHouse数据仓库中的表

设计一个MySQL数据库和Clickhouse数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...