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

news2025/1/16 13:53:59

目录

一、程序编写背景

二、编程思路讲解

- 类图

- 实现逻辑

- 工厂模式

- 模板方法模式

  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{
    
        @Resource
        private RecognizeTemplateMapper recognizeTemplateMapper;
        @Resource
        private SystemConfigService systemConfigService;
    
        @Autowired
        private AsyncOcrRecognizeLogService asyncOcrRecognizeLogService;
    
        @Resource
        private 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 {
        @Override
        public 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 {
    
        @Resource
        private ProjectConfig projectConfig;
    
        @Override
        public 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.coloradmin.cn/o/1442390.html

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

相关文章

租用海外服务器丢包是什么情况?

在当今的互联网时代&#xff0c;海外服务器租用已经成为了许多企业和个人的选择。然而&#xff0c;在使用海外服务器的过程中&#xff0c;有时会出现丢包的情况&#xff0c;这给用户带来了不小的困扰。那么&#xff0c;租用海外服务器丢包是什么情况呢&#xff1f;本文将对此进…

【Python】Mac 本地部署 stable-diffusion

其实要在本地部署 stable-diffusion 不难&#xff0c;只要有“魔法”一切都水到渠成&#xff0c;如下图&#xff1a; (base) MacBook-Pro python % git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui Cloning into stable-diffusion-webui... remote: Enu…

开发JSP应用程序

开发JSP应用程序 问题陈述 TecknoSoft Pvt Ltd.公司的首席技术官(CTO)John Barrett将创建一个应用程序的任务委托给了开发团队,该应用程序应在客户访问其账户详细信息前验证其客户ID和密码。客户ID应是数字形式。John希望如果所输入的客户ID或密码不正确,应向客户显示错误…

2.7日学习打卡----初学RabbitMQ(二)

2.7日学习打卡 JMS 由于MQ产品很多&#xff0c;操作方式各有不同&#xff0c;于是JAVA提供了一套规则 ——JMS&#xff0c;用于操作消息中间件。JMS即Java消息服务 &#xff08;JavaMessage Service&#xff09;应用程序接口&#xff0c;是一个Java平台中关于面 向消息中间件的…

ssm+vue的医药垃圾分类管理系统(有报告)。Javaee项目,ssm vue前后端分离项目。

演示视频&#xff1a; ssmvue的医药垃圾分类管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;ssm vue前后端分离项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结…

在本地运行大型语言模型 (LLM) 的六种方法(2024 年 1 月)

一、说明 &#xff08;开放&#xff09;本地大型语言模型&#xff08;LLM&#xff09;&#xff0c;特别是在 Meta 发布LLaMA和后Llama 2&#xff0c;变得越来越好&#xff0c;并且被越来越广泛地采用。 在本文中&#xff0c;我想演示在本地&#xff08;即在您的计算机上&#x…

Android 粒子喷泉动效

一、前言&#xff1a; 在学习open gl es实现动效的时候&#xff0c;打算回顾了一下用普通的2D坐标系实现粒子效果和 open gl 3d 坐标系的区别&#xff0c;以及难易程度&#xff0c;因此本篇以Canvas 2D坐标系实现了一个简单的demo。 粒子动效原理&#xff1a; 粒子动效本质上…

504. Base 7(七进制数)

题目描述 给定一个整数 num&#xff0c;将其转化为 7 进制&#xff0c;并以字符串形式输出。 问题分析 按照二进制转换的方式进行转换即可 代码 char* convertToBase7(int num) {int count 0;char *x (char *)malloc(sizeof(char)*32);char *y (char *)malloc(sizeof(c…

【Redis】深入理解 Redis 常用数据类型源码及底层实现(3.详解String数据结构)

【Redis】深入理解 Redis 常用数据类型源码及底层实现&#xff08;1.结构与源码概述&#xff09;-CSDN博客 【Redis】深入理解 Redis 常用数据类型源码及底层实现(2.版本区别dictEntry & redisObject详解)-CSDN博客 紧接着前两篇的总体介绍&#xff0c;从这篇开始&#x…

windows安装sqlite

windows安装sqlite比linux麻烦很多 1.下载 下载链接&#xff1a;链接 下载dll的zip文件 2.解压并放到文件夹 将压缩包内的文件解压&#xff0c;放到C://sqlite下 3.编辑环境变量 添加到系统变量的path中 4.验证 打开命令提示符&#xff0c;输入 sqlite3有结果就行

JavaWeb02-MyBatis

目录 一、MyBatis 1.概述 2.JavaEE三层架构简单介绍 &#xff08;1&#xff09;表现层 &#xff08;2&#xff09;业务层 &#xff08;3&#xff09;持久层 3.框架 4.优势 &#xff08;1&#xff09;JDBC的劣势 &#xff08;2&#xff09;MyBatis优化 5.使用 &#…

Golang的for循环变量和goroutine的陷阱,1.22版本的更新

先来看一段golang 1.22版本之前的for循环的代码 package mainimport "fmt"func main() {done : make(chan bool)values : []string{"chen", "hai", "feng"}for _, v : range values {fmt.Println("start")go func() {fmt.P…

Gemini 下一章节即将拉开帷幕

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

树与二叉树---数据结构

树作为一种逻辑结构&#xff0c;同时也是一种分层结构&#xff0c;具有以下两个特点&#xff1a; 1&#xff09;树的根结点没有前驱&#xff0c;除根结点外的所有结点有 且只有一个前驱。 2&#xff09;树中所有结点可以有零个或多个后继。 树结点数据结构 满二叉树和完全二…

洛谷使用指南

详细看——洛谷的规则 1.注册账号 1.打开洛谷首页 这样就对了&#xff01;&#xff01;&#xff01; 2.点击注册 当显示以上页面时表示进入了注册页面。 3.登录 当注册好后就可以登陆了。 当显示以上页面时表示进入了登录页面。 2.题库使用 当单击题库后&#xff0c;会出…

算法练习-二叉搜索树中的搜索(思路+流程图+代码)

难度参考 难度&#xff1a;中等 分类&#xff1a;二叉树 难度与分类由我所参与的培训课程提供&#xff0c;但需要注意的是&#xff0c;难度与分类仅供参考。且所在课程未提供测试平台&#xff0c;故实现代码主要为自行测试的那种&#xff0c;以下内容均为个人笔记&#xff0c;旨…

二、OpenAI开发者快速入门

启动并运行OpenAI API OpenAI API 为开发者提供一个简单的接口&#xff0c;使其能够在他们的应用中创建一个智能层&#xff0c;由OpenAI最先进的模型提供支持。聊天补全端点为ChatGPT提示支持&#xff0c;一种简单的方法是&#xff1a;输入文本&#xff0c;使用GPT-4模型输出。…

在JSP中实现JAVABEAN

在JSP中实现JAVABEAN 问题陈述 创建Web应用程序以连接数据库并检索作者名、地址、城市、州及邮政编码等与作者的详细信息。JavaBean组件应接受作者ID、驱动程序名及URL作为参数。信息要从authors表中检索。 解决方案 要解决上述问题,需要执行以下任务: 创建Web应用程序。创…

macbookair怎么清理内存 ?如何利用 CleanMyMac X 进行系统清理

macbookair怎么清理内存 清理MacBook Air的内存可以通过以下几种方法&#xff1a; 优化储存空间。在MacBook Air上&#xff0c;可以通过“优化储存空间”来释放空间。这包括将文件储存在iCloud中&#xff0c;如桌面、文稿和iCloud信息&#xff0c;以及自动移除在iCloud中观看…

Lombok 高级说明

优质博文&#xff1a;IT-BLOG-CN 一、痛点 【1】代码臃肿&#xff1a;POJO中的getter/setter/equals/hashcode/toString等&#xff1b; 【2】样板式代码&#xff1a;I/O流的关闭操作等&#xff1b; Lombok是一个可以通过注解简化Java代码开发的工具&#xff0c;能够在我们编…