架构之模板方法等模式的使用

目录

一、程序编写背景

二、编程思路讲解

- 类图

- 实现逻辑

- 工厂模式

- 模板方法模式

  1. 接口类(代码)
  2. 抽象类(代码)
  3. 具体实现类(代码)
  4. 工厂类(代码)
  5. 注册类(代码)
  6. 系统启动加载(代码)
  7. 系统启动加载 - 初始化方法(代码)

总结

  1. 类图绘制
  2. UML图型使用
  3. 设计模式理解
  4. 推荐书籍

一、背景

1. 业务需要使用ocr场景对图片进行识别。但由于前期使用的TesserOcr识别率不是特别高。故又需要新的识别方式。
2. 在确定使用paddleocr后,对程序进行修改。为了兼容两种ocr使用方式。
3. 通过配置yml文件的方式可以在使用时对两种ocr识别方式进行切换使用。(也可配置入数据库进行动态配置)

具体的Ocr识别教程可参照其他文章

TesseractOcr(开源ocr)

  • 安装及使用此部分内容后期待补充

PaddleOcr (开源ocr)

  • paddleocr的安装及使用此部分内容后期待补充
  • 使用pyinstall打包 >> 👀
  • paddleocr模型的训练 此部分内容后期待补充

二、编程思路讲解

首先上类图。可以较直观表现了调用关系

在这里插入图片描述

1. 实现逻辑

简单描述了程序调用顺序

1. 手动配置yml中ocr类型(可配置入数据库进行动态配置)。
2. 程序启动时将两种ocr服务对象加载入缓存。
3. 业务进行时,程序识别会通过传入参数获取对应类型的orc服务对象进行识别服务。
2. 工厂模式

创建TesseractOcr与PaddleOcr使用

import service.ocrservice.recognize.OcrMultiParamRecognize;
import service.ocrservice.recognize.OcrNomralRecognize;
import service.ocrservice.recognize.PaddleOcrRecognize;
import com.msun.cloud.dcm.util.Direct;import java.io.File;public class RecognizeFactory {/*** TesseractOcr识别*/public static Recognize getRecognize(String dataPath, File pendingFile, Direct patientDirect, Direct accnumDirect, String formateName, String dpi) {return new OcrNomralRecognize(dataPath, pendingFile, patientDirect, accnumDirect, formateName, dpi);}/*** paddleOcr识别*/public static Recognize getPaddleOcrRecognize(String filePath, Direct patientDirect, Direct accnumDirect, String formateName) {return new PaddleOcrRecognize(filePath, formateName, patientDirect, accnumDirect);}
}
3. 模板方法模式

粘贴内容还包括使用工厂模式创建对象

  • 接口类
    提供了业务在调用Ocr服务类对象时的统一接口,表现了面向接口编程的思想
    package service.ocrservice;import entity.PO.Patient;
    import PO.RecognizeTemplate;import java.io.File;/*** 通过ocr识别获取患者信息*/
    public interface OcrPatientService {Patient getRecognizedPatient(File pendingFile, String aeTitle, String spFilePath, String formateName, RecognizeTemplate recognizeTemplate);Recognize getRecognize(File pendingFile, RecognizeTemplate template, String formatName);}
  • 抽象类
    封装了公共方法,子类实现抽象类中的抽象方法。公共方法对抽象方法进行调用
    package service.ocrservice;import com.alibaba.fastjson.JSON;
    import entity.BO.OcrRecognizeLog;
    import entity.PO.Patient;
    import entity.PO.RecognizeTemplate;
    import entity.common.Const;
    import mapper.PatientMapper;
    import mapper.RecognizeTemplateMapper;
    import service.SystemConfigService;
    import service.ocrservice.entity.RecognizeEntity;
    import service.ocrservice.service.AsyncOcrRecognizeLogService;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;import javax.annotation.Resource;
    import java.io.File;
    import java.util.List;@Slf4j
    public abstract class AbstractOcrPatientServiceImpl implements OcrPatientService{@Resourceprivate RecognizeTemplateMapper recognizeTemplateMapper;@Resourceprivate SystemConfigService systemConfigService;@Autowiredprivate AsyncOcrRecognizeLogService asyncOcrRecognizeLogService;@Resourceprivate PatientMapper patientMapper;/*** 获取识别的人员信息* @return*/public Patient getRecognizedPatient(File pendingFile, String aeTitle, String spFilePath, String formateName, RecognizeTemplate recognizeTemplate) {Patient patient = null;try{# 抽象方法调用patient = recognize(dataPath, pendingFile, template, formateName);} finally {...}return patient;}public abstract Patient recognize(String dataPath, File pendingFile, RecognizeTemplate template, String formatName);private void insertExOcrRecord(Patient patient, String aeTitle, String spFilePath) {... 插入日志}protected Patient queryPatient(RecognizeEntity entity) {... 查询人员信息}}
  • 具体实现类
    package com.msun.cloud.dcm.service.ocrservice.impl;import com.msun.cloud.dcm.entity.PO.Patient;
    import com.msun.cloud.dcm.entity.PO.RecognizeTemplate;
    import com.msun.cloud.dcm.service.ocrservice.AbstractOcrPatientServiceImpl;
    import com.msun.cloud.dcm.service.ocrservice.OcrPatientService;
    import com.msun.cloud.dcm.service.ocrservice.Recognize;
    import com.msun.cloud.dcm.service.ocrservice.RecognizeFactory;
    import com.msun.cloud.dcm.util.Direct;
    import org.springframework.stereotype.Service;import java.io.File;
    import java.util.function.Consumer;@Service
    public class PaddleOcrPatientServiceImpl extends AbstractOcrPatientServiceImpl {@Overridepublic Patient recognize(String dataPath, File pendingFile, RecognizeTemplate template, String formatName) {Direct patientDirect = new Direct(template.getPatientRecognizeX(), template.getPatientRecognizeY(), template.getPatientRecognizeW(), template.getPatientRecognizeH());Direct accNumDirect = new Direct(template.getAccnumRecognizeX(), template.getAccnumRecognizeY(), template.getAccnumRecognizeW(), template.getAccnumRecognizeH());Recognize recognize = RecognizeFactory.getPaddleOcrRecognize(pendingFile.getAbsolutePath(), patientDirect, accNumDirect, formatName);if("1".equals(template.getIsReBuild())){return queryPatient3D(recognize.recognize());}return queryPatient(recognize.recognize());}public Recognize getRecognize(File pendingFile, RecognizeTemplate template, String formatName) {Direct patientDirect = new Direct(template.getPatientRecognizeX(), template.getPatientRecognizeY(), template.getPatientRecognizeW(), template.getPatientRecognizeH());Direct accNumDirect = new Direct(template.getAccnumRecognizeX(), template.getAccnumRecognizeY(), template.getAccnumRecognizeW(), template.getAccnumRecognizeH());Recognize recognize = RecognizeFactory.getPaddleOcrRecognize(pendingFile.getAbsolutePath(), patientDirect, accNumDirect, formatName);return recognize;}
    }
    
  • 工厂类
    import ocrservice.recognize.OcrMultiParamRecognize;
    import ocrservice.recognize.OcrNomralRecognize;
    import ocrservice.recognize.PaddleOcrRecognize;
    import util.Direct;import java.io.File;public class RecognizeFactory {/*** 范围识别* @param dataPath* @param pendingFile* @param patientDirect* @param formateName* @param dpi* @return*/public static Recognize getRecognize(String dataPath, File pendingFile, Direct patientDirect, String formateName, String dpi) {return new OcrMultiParamRecognize(dataPath, pendingFile, patientDirect, formateName, dpi);}/*** 精确识别* @param dataPath* @param pendingFile* @param patientDirect* @param formateName* @param dpi* @return*/public static Recognize getRecognize(String dataPath, File pendingFile, Direct patientDirect, Direct accnumDirect, String formateName, String dpi) {return new OcrNomralRecognize(dataPath, pendingFile, patientDirect, accnumDirect, formateName, dpi);}public static Recognize getPaddleOcrRecognize(String filePath, Direct patientDirect, Direct accnumDirect, String formateName) {return new PaddleOcrRecognize(filePath, formateName, patientDirect, accnumDirect);}
    }
    
  • 注册类(包含枚举类)
    package service.ocrservice;import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Component;import java.util.Arrays;
    import java.util.HashMap;
    import java.util.Map;/*** 收集 ocr 服务类*/
    @Component
    public class OcrServiceRegistry {public static Map<OcrType, OcrPatientService> registryMap = new HashMap();public static OcrPatientService ocrPatientServiceCache;...public enum OcrType {TesserOcr("1"),PaddleOcr("2");private String code;OcrType(String code) {this.code = code;}public static OcrType getOcrTypeByCode(String code) {for (int i = 0; i < OcrType.values().length; i++) {OcrType ocrType = OcrType.values()[i];if(ocrType.code.equals(code)) return ocrType;}return TesserOcr;}}public static OcrPatientService getOcrService(String ocrTypeCode) {if(ocrPatientServiceCache == null) {ocrPatientServiceCache = registryMap.get(OcrType.getOcrTypeByCode(ocrTypeCode));}return ocrPatientServiceCache;}
    }
    
  • 系统启动加载
    import lombok.Data;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.boot.ApplicationArguments;
    import org.springframework.boot.ApplicationRunner;
    import org.springframework.data.redis.listener.RedisMessageListenerContainer;
    import org.springframework.stereotype.Component;import javax.annotation.Resource;/*** 初始化工具类*/
    @Slf4j
    @Data
    @Component
    public class PostApplicationRunner implements ApplicationRunner {@Resourceprivate ProjectConfig projectConfig;@Overridepublic void run(ApplicationArguments args) throws Exception {PrintDcmOcrRecognizeService.init();}
    }
  • 系统启动加载 - 初始化方法
    public class PrintDcmOcrRecognizeService {public static void init() {OcrServiceRegistry.registryMap.put(OcrServiceRegistry.OcrType.TesserOcr, SpringUtils.getBean(TessOcrPatientServiceImpl.class));OcrServiceRegistry.registryMap.put(OcrServiceRegistry.OcrType.PaddleOcr, SpringUtils.getBean(PaddleOcrPatientServiceImpl.class));}
    }
    

三、总结

  1. 类图绘制。
    类图绘制为后期加入的。前期没有做类图中框架的设计,模式的使用是可以是根据业务的需要而做的。在编程中对业务架构中每一个部分做了设计。最后的总结才有了这个样子。类图参照《大话设计模式》一书
    在这里插入图片描述

  2. UML图型使用。
    UML类图中图型的使用是参照《大话设计模式》中UML类讲解 >> | 使用的。

  3. 设计模式理解。
    目前经常用到的设计模式种类不多。基本为工厂、模板、享元、静态代理。设计模式虽多,但不宜滥用,过度设计,因为设计的初衷是根据业务的需要,使得代码更加容易阅读和拓展。

  4. 推荐书籍。
    -《大话设计模式》使用讲Demo的方式有趣介绍了模式的使用,其中的UML类图使用较多
    -《设计模式之美》根据实际业务场景讲解了何时要用到设计模式。内容易懂,对工作帮助比较大 可以在有了设计模式基础后去读一读

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python爬虫实战:抓取猫眼电影排行榜top100#4

爬虫专栏系列&#xff1a;http://t.csdnimg.cn/Oiun0 抓取猫眼电影排行 本节中&#xff0c;我们利用 requests 库和正则表达式来抓取猫眼电影 TOP100 的相关内容。requests 比 urllib 使用更加方便&#xff0c;而且目前我们还没有系统学习 HTML 解析库&#xff0c;所以这里就…

LiteFlow规则引擎框架

LiteFlow规则引擎框架 Hi&#xff0c;我是阿昌&#xff0c;今天介绍一个规则引擎框架&#xff0c;LiteFlow&#xff1b; 一、前言 那首先得知道什么是规则引擎&#xff1f;规则引擎是 一种用于自动化处理业务规则的软件组件。 在软件行业中&#xff0c;规则引擎通常用于解决…

如何使用Docker本地部署一个开源网址导航页并分享好友公网使用

&#x1f525;博客主页&#xff1a; 小羊失眠啦. &#x1f3a5;系列专栏&#xff1a;《C语言》 《数据结构》 《Linux》《Cpolar》 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;…

备战蓝桥杯---动态规划(基础3)

本专题主要介绍在求序列的经典问题上dp的应用。 我们上次用前缀和来解决&#xff0c;这次让我们用dp解决把 我们参考不下降子序列的思路&#xff0c;可以令f[i]为以i结尾的最大字段和&#xff0c;易得&#xff1a; f[i]max(a[i],a[i]f[i-1]); 下面是AC代码&#xff1a; #in…

有哪些方法可以配置并发服务器?

通过合理配置并发服务器&#xff0c;可以提高服务器的处理能力和响应速度&#xff0c;从而更好地满足用户需求。本文将介绍一些常见的并发服务器配置方法&#xff0c;以帮助您更好地实现服务器的高效运行。 一、选择合适的操作系统 操作系统的选择是并发服务器配置的重要环节…

【数据结构与算法-初学者指南】【附带力扣原题】队列

&#x1f389;&#x1f389;欢迎光临&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;特别推荐给大家我的最新专栏《数据结构与算法&#xff1a;初学者入门指南》&#x1f4d8;&am…

面向数据报编程-UDP协议

目录 前言&#xff1a; 1.UDP协议API 1.1UDP编程原理 1.2DatagramSocket类 &#xff08;1&#xff09;DatagramSocket构造方法 &#xff08;2&#xff09;DatagramSocket普通方法 1.3DatagramPacket类 &#xff08;1&#xff09;DatagramPacket构造方法 &#xff08;2…

2.6日学习打卡----初学RabbitMQ(一)

2.6日学习打卡 初识RabbitMQ、 一. MQ 消息队列 MQ全称Message Queue&#xff08;消息队列&#xff09;&#xff0c;是在消息的传输过程中保 存消息的容器。多用于系统之间的异步通信。 同步通信相当于两个人当面对话&#xff0c;你一言我一语。必须及时回复 异步通信相当于通…

vs用msys2编译安装 gmp

1 下载 1.1下载MSYS2工具 MSYS2 1.2 下载gmp The GNU MP Bignum Library 2 使用windows的msys2命令窗口,有三个msys2命名窗口 mingw64 3 4 命令 pacman -Syu 重启&#xff1a; pacman -Su 安装&#xff1a; pacman -S mingw-w64-x86_64-gcc pacman -S mingw-w64-x86_64-make…

C语言函数的栈帧与销毁(面试亮点)

目录 如果你能熟练的掌握函数的栈帧与销毁在面试中是及其亮眼的加分项&#xff0c;所以我们来以实例来将解函数是如何实现栈帧与销毁的。 一. 函数栈帧 二.寄存器 三. 用例题讲解创建栈帧的过程 3.1 main 函数的反汇编代码。 第一步&#xff1a;给调用main函数的函数分配…

[职场] 如何通过运营面试_1 #笔记#媒体#经验分享

如何通过运营面试 盈利是公司的事情&#xff0c;而用户就是你运营的事情。你需要彻底建立一个庞大而有效的用户群&#xff0c;这样才能让你们的公司想盈利就盈利&#xff0c;想战略就战略&#xff0c;想融资就融资。 一般从事运营的人有着强大的自信心&#xff0c;后台数据分析…

JVM-虚拟机栈

虚拟机栈 Java虚拟机栈&#xff08;Java Virtual Machine Stack&#xff09;采用栈的数据结构来管理方法调用中的基本数据&#xff0c;先进后出&#xff08;First In Last Out&#xff09;,每一个方法的调用使用一个栈帧&#xff08;Stack Frame&#xff09;来保存。 接下来以…

vue3 之 通用组件统一注册全局

components/index.js // 把components中的所组件都进行全局化注册 // 通过插件的方式 import ImageView from ./ImageView/index.vue import Sku from ./XtxSku/index.vue export const componentPlugin {install (app) {// app.component(组件名字&#xff0c;组件配置对象)…

D7 Elasticsearch-Mongodb(搜索记录)

我是南城余&#xff01;阿里云开发者平台专家博士证书获得者&#xff01; 欢迎关注我的博客&#xff01;一同成长&#xff01; 一名从事运维开发的worker&#xff0c;记录分享学习。 专注于AI&#xff0c;运维开发&#xff0c;windows Linux 系统领域的分享&#xff01; 知…

mysql笔记:表设计原则

mysql笔记&#xff1a;表设计原则 表对应了一个实体 表与表之间的关系&#xff1a; 一对一 一对多 多对多 一对一关系 例如&#xff1a;用户 user和身份信息 info 子表的外键关联了父表的子健&#xff08;类型必须一样&#xff09; 一对多关系 以电商系统为例子 用户-商…

CSP-202012-1-期末预测之安全指数

CSP-202012-1-期末预测之安全指数 题目很简单&#xff0c;直接上代码 #include <iostream> using namespace std; int main() {int n, sum 0;cin >> n;for (int i 0; i < n; i){int w, score;cin >> w >> score;sum w * score;}if (sum > 0…

使用 Ant Design 的 Upload 组件实现图片

文章目录 使用 Ant Design 的 Upload 组件实现图片Upload组件itemRender自定义上传列表项的渲染方式修改图片名上传图片上传链接中添加 Bearer Token 的请求头onPreview{handlePreview}上传成功后&#xff0c;如何隐藏上传列表 使用 Ant Design 的 Upload 组件实现图片 Upload…

【第二十三课】最小生成树:prime 和 kruskal 算法(acwing858,859 / c++代码 )

目录 前言 Prime算法--加点法 acwing-858 代码如下 一些解释 Kruskal算法--加边法 acwing-859 并查集与克鲁斯卡尔求最小生成树 代码如下 一些解释 前言 之前学最短路的时候&#xff0c;我们都是以有向图为基础的&#xff0c;当时我们提到如果是无向图&#xf…

【深度学习】实验7布置,图像超分辨

清华大学驭风计划 因为篇幅原因实验答案分开上传&#xff0c; 实验答案链接http://t.csdnimg.cn/P1yJF 如果需要更详细的实验报告或者代码可以私聊博主 有任何疑问或者问题&#xff0c;也欢迎私信博主&#xff0c;大家可以相互讨论交流哟~~ 深度学习训练营 案例 7 &#xff1…

计算机毕业设计Python+django医院后勤服务系统flask

结合目前流行的 B/S架构&#xff0c;将医疗后勤服务管理的各个方面都集中到数据库中&#xff0c;以便于用户的需要。该平台在确保平台稳定的前提下&#xff0c;能够实现多功能模块的设计和应用。该平台由管理员功能模块,工作人员模块&#xff0c;患者模块&#xff0c;患者家属模…