策略模式在AIBOT项目中的实际应用

原文链接icon-default.png?t=N7T8https://www.jylt.cc/#/detail?activityIndex=2&id=8d1912358fa1c1d8db1b44e2d1042b70AIBOT 你想 我来做AIBOTicon-default.png?t=N7T8https://chat.jylt.top/

定义

策略模式(Strategy Pattern:Define a family of algorithms,encapsulate each one,and make them interchangeable.)中文解释为:定义一组算法,然后将这些算法封装起来,以便它们之间可以互换,属于一种对象行为型模式。总的来说策略模式是一种比较简单的模式,听起来可能有点费劲,其实就是定义一组通用算法的上层接口,各个算法实现类实现该算法接口,封装模块使用类似于 Context 的概念,Context 暴漏一组接口,Context 内部接口委托到抽象算法层。

是不是每个字都能看懂,拼到一块不知所以然了。最初看到这句话时也不知道啥意思,下面有一个类图供大家看下:

组成角色很简单,对于新手来说,实现起来可能会毫无思路。其实主要使用的就是多态的特性。

实现

了解了基本概念之后,可能对策略模式仅仅是一个了解的状态,动手实操可能还没有什么思路。下面以我的AI项目AIBOT中图片生成功能来说一下策略模式是如何落地的。

先看一下具体的功能点:

https://oss.jylt.cc/img/content/32ef85ebfc3b3eb8ef83903ee3757cc0/609cf46a-27ff-4447-aa08-4a19d25e52c4.png

目前AI作图只有两个功能,文生图和人像重绘,如何实现这两个功能呢?

普通实现方式

最简单高效的方法是平铺直叙的写代码,通过 if-else 来区分具体是哪个功能,例如:

    @PostMapping("/genImg")
    public ResponseKit<Object> genImg(int type) {
        if (type == 1) {
            // 文生图逻辑
        } else if (type == 2) {
            // 人像重绘逻辑
        } else if (type == ...) {
            // 其他图像生成逻辑
        }
    }
优点
  • 代码实现方便,不需要做过多设计
  • 代码条理比较清晰,自上而下很容易找出来哪块逻辑实现的是什么功能
缺点
  • 会增加类的复杂性,这些逻辑虽都是图片生成,但具体实现逻辑不是同一类,都放到同一个类中,会使这个类变得大而全,与 职责单一 的设计规范相冲突
  • 如果日后需要增加其他图像生成逻辑,需要频繁的修改这个类,而这个类中又有太多其他生成规则的逻辑,修改、新增逻辑可能会对其他已有逻辑造成意料之外的影响,为了避免这种影响可能引入的错误,我们就要对受影响的逻辑都要进行回归测试。这样无形间增加了测试的工作量,与 开闭原则 设计规范相冲突
策略模式实现

依据上面的类图,我们先一步步通过策略模式来实现功能,然后来看一下策略模式有什么优缺点

首先我们需要先定义一个通用接口:

public interface GenImgStrategy {
    ResponseKit<Object> genImg();
}

接口很简单,就一个抽象方法:生成图片;然后我们定义一下 文生图 和 人像重绘 的具体实现逻辑。这两个逻辑都统一实现 GenImgStrategy 接口:

public class TextToImgStrategyImpl implemets GenImgStrategy {
    @Override
    public ResponseKit<Object> gen() {
  	// 文生图具体实现逻辑
    }
}

public class GenImgStyleStrategyImpl implemets GenImgStrategy {
    @Override
    public ResponseKit<Object> gen() {
  	// 人像重绘具体实现逻辑
    }
}

定义好了接口和实现类之后,我们如何通过 API 接口中的 type 参数来确定需要执行 文生图 的逻辑还是执行 人像重绘 的逻辑呢?这时候我们需要一个辅助类:

public class GenImgStrategyContext {

    private static final Map<Integer, GenImgStrategy> map = new HashMap<>();

    static {
	// 初始化
        map.put(1, new TextToImgStrategyImpl());
        map.put(2, new GenImgStyleStrategyImpl());
  	map.put(..., ...);
    }

    // type=1:执行文生图逻辑;type=2:执行人像重绘逻辑
    public ResponseKit<Object> doGen(Integer type) {
        GenImgStrategy genImgStrategy = map.get(type);
        if (genImgStrategy == null) {
            log.error("类型异常,type={}", type);
            return ResponseKit.error("参数异常");
        }
        return genImgStrategy.gen();
    }
}

这里使用多态的特性,在执行 doGen 方法的时候,通过 type 值来获取不同策略的具体实现类,最后执行 gen 方法的时候,其实执行的是具体实现类中的方法

API 接口只需要改为以下形式,就可以轻松调用不同的图像生成逻辑了:

    @PostMapping("/genImg")
    public ResponseKit<Object> genImg(int type) {
       GenImgStrategyContext context = new GenImgStrategyContext();
       return context.doGen(type);
    }

这样改造之后,我们就通过 策略模式 来实现了图片生成的两种实现逻辑,后续如果有新的图片生成逻辑,只需要再增加一个实现类,在 context 类的 map 中再增加一种类型即可,对现有的两种实现逻辑实现了零侵入,做功能验证的时候只需要验证新增的逻辑即可,无需担心对现有功能的其他影响。

综合以上,我们看一下策略模式的优缺点:

优点
  • 极大的提高了程序的扩展性
  • 使程序更加的 高内聚,低耦合
  • 提高了后续功能扩展的效率
缺点
  • 增加了程序的复杂性
  • 如果策略较多,会有很多的策略实现类

看到这里之后,有些小伙伴可能还是懵懵懂懂的状态,毕竟纸上得来终觉浅,需要动手实操,最好是在自己的项目中实践一下,立即会有柳暗花明又一村的感觉。

这些都是我的真实感受,我在2020年就去有意识的学习了各种设计模式,但一直没有使用场景,也就只停留在了解的层面,知道有这么个概念,直到两个月前,在团队项目中实际看到了同事使用策略模式来解决实际问题的代码,瞬间豁然开朗,原来是这么用的。然后就在图像生成的功能上使用了,好处确实很明显。

除此之外,AIBOT 中在支付功能也是用了策略模式,来实现 会员、图像、单次充值的不同场景。

总结

策略模式虽然好处多多,但技术没有银弹,合适的才是最好的。对于经常变更策略的场景,策略模式确实能够更好的选择,但是如果不加选择的使用策略模式,会不自觉陷入过度设计的陷阱

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

生成芭比系列咒语

咒语&#xff1a;Close-up of a man with golden hair and a necklace,Digital Art Inspired by Cheng Yanjun, Tumblr,Rococo,Portrait of Josie in Black Pink,Portrait Zhixiu Black Pink,flowing golden hair,long flowing golden hair,Bubble Gum Long Hair,blond hair,Pi…

电信联通5G共建共享方案实施及验证

一、情况概述 随着2019年9月9日中国电信集团与联通签署《5G网络共建共享框架合作协议书》&#xff0c;电信与联通在全国范围内合作共建5G接入网络。根据合作协议&#xff0c;联通运营公司将与中国电信在全国范围内合作共建一张5G接入网络, 双方划定区域&#xff0c;分区建设&a…

前端开发中的那些规范

开发中的那些规范 俗话说&#xff1a;无规矩不成方圆。生活如此、软件开发也如此。 来聊一聊开发中有哪些地方需要规范。 为什么需要规范 现在开发一个应用基本上都是多人协作&#xff0c;一旦涉及到多人&#xff0c;必然不同的开发者的开发习惯、编码方式都是有所不同的&…

SpringBoot整合ElasticSearch实现基础的CRUD操作

本文来说下SpringBoot整合ES实现CRUD操作 文章目录 概述spring-boot-starter-data-elasticsearch项目搭建ES简单的crud操作保存数据修改数据查看数据删除数据 本文小结 概述 SpringBoot支持两种技术和es交互。一种的jest&#xff0c;还有一种就是SpringData-ElasticSearch。根据…

【C语言入门】交换两个变量的值(三种方法)

✨✨欢迎大家来到Celia的博客✨✨ &#x1f389;&#x1f389;创作不易&#xff0c;请点赞关注&#xff0c;多多支持哦&#x1f389;&#x1f389; 所属专栏&#xff1a;C语言 个人主页&#xff1a;Celias blog~ 引言 我们在编写程序时&#xff0c;经常会需要交换两个变量的值&…

Shell脚本③条件语句、if命令和case命令

目录 一.条件语句 1.test测试条件表达式 2.整数数值比较 &#xff08;1&#xff09;比较两个整数大小 &#xff08;2&#xff09;查看系统剩余内存是否低于1024M 3.逻辑测试 4.三元运算符 二.if命令 1.单分支结构 2.双分支结构 3.多分支结构 三.case语句 四.脚本 …

cmd_to_robot 讨论及 G29 控制优化

cmd_to_robot 讨论及 G29 控制优化 cmd_to_robot 讨论 转向电机控制代码中&#xff0c;补偿信息在循环中发布&#xff0c;转向完成信息在回调函数中发布 转动电机控制代码中&#xff0c;对转动电机的控制在转向完成的回调函数中实现 这就意味着如果一直没有 /cmd_vel 消息发…

基于springboot+vue的学科竞赛管理系统(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 研究背景…

零日漏洞:威胁与应对

一、引言 随着信息技术的迅猛发展&#xff0c;网络安全问题日益凸显。其中&#xff0c;零日漏洞已成为当今网络安全领域最受关注的问题之一。本文将深入探讨零日漏洞的威胁、产生原因以及应对策略&#xff0c;以期提高人们对这一问题的认识和防范意识。 二、零日漏洞的威胁 …

Java - 数字签名与数字证书

文章目录 概述对称加密非对称加密数字签名数字证书根证书申请ca证书 完整流程小结 概述 SSL是一种安全协议&#xff0c;用于在网络传输中提供数据加密、身份验证和完整性保护。它基于传输层协议&#xff08;如TCP&#xff09;&#xff0c;并为其提供加密和安全功能。 对称加密…

LLM之RAG理论(七)| 高提升RAG检索的四种方法

​ RAG两大核心组件&#xff1a;检索和生成。本文将总结四种提高RAG系统检索质量的技术&#xff1a;1&#xff09;子问题查询引擎&#xff08;来自LlamaIndex&#xff09;&#xff0c;2&#xff09;RAG-Fusion、3&#xff09;RAG-end2end和4&#xff09;LoRA微调。 一、L…

如何用GPT绘图?

详情点击练级&#xff1a;如何用GPT绘图&#xff1f; 一OpenAI 1.最新大模型GPT-4 Turbo 2.最新发布的高级数据分析&#xff0c;AI画图&#xff0c;图像识别&#xff0c;文档API 3.GPT Store 4.从0到1创建自己的GPT应用 5. 模型Gemini以及大模型Claude2 二定制自己的GPTs…

多线程select并发

多线程select并发 只需要在上面代码的基础上对服务器端做些更改, 主要逻辑如下: 主线程在检测到有新的客户端连接之后, 创建一个子线程完成accept操作, 具体如下: if(FD_ISSET(lfd, &rdtemp)){auto* info new fdInfo;info->fd lfd;info->maxfd &maxfd;info…

grid布局,flex布局实现类似响应式布局的效果

一. grid布局 实现代码 <!DOCTYPE html> <html lang"en"><head><style>.box {display: grid;grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); /*自动填充&#xff0c;最小宽度300px*/justify-content: space-between;gap:…

go语言(十六)----tag

package mainimport ("fmt""reflect" )type resume struct {Name string info:"name" doc:"我的名字"Sex string info:"sex" }func findTag(str interface{}) {t : reflect.TypeOf(str).Elem()for i : 0;i < t.NumField…

redis高可用之Sentinel模式

文章目录 前言1. 创建联想主服务器的网络连接2. 创建连向其他Sentinel的命令连接 &#xff08;也就是调度中心的高可用&#xff09;3.选举领头Sentinel 调度中心高可用4.故障转移 选出新的主服务器 redis服务器高可用如何挑选新的主服务器&#xff1f; 总结 前言 Sentinel(哨岗…

【Keil5】keil5修改主题背景颜色--仿VS Code 主题

keil单调的白底主题难免会让人产生视觉疲劳&#xff0c;该工具里有仿VS的黑色主题.当然&#xff0c;如果你觉得这些都不合你心意也可自己制作配色方案。 1、备份 C:\Keil_v5\UV4下的 global.prop文件。 2、下或者复制 我配置的global.prop文件到你的Keil安装路径&#xff0c;比…

什么是护网行动?

护网&#xff0c;也称“网络保护”&#xff0c;是指网络安全人员对企业或组织的网络进行检查、维护和保护&#xff0c;以防止网络受到黑客攻击、病毒、木马或其它恶意程序的侵入和损害。护网工作包括&#xff1a;网络安全规划、网络配置和控制、漏洞发现和修复、入侵检测和防范…

jenkins 使用webhooks 触发构建任务gitea为例 gitlab类似

jenkins 使用webhooks 触发构建任务gitea为例 多次尝试以及网上的各种资料查阅成功了下 其他人给的答案他们有他们的道理&#xff0c;至少我没有实验成功。我这里就记录下 添加API token 将生成的token 复制保存 第4步骤的时候要用 配置构建方式 填写身份验证令牌 安全配…

Spring复习-问题回答

1.什么是 spring&#xff0c;你对 spring 的理解? Spring是一个轻量级&#xff0c;非侵入式的&#xff08;不使用框架特定的类&#xff0c;感受不到框架&#xff09;IOC和AOP一站式的java后端开发框架&#xff0c;简化企业开发。 2.spring 的优缺点 优点&#xff1a; Spr…