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

工厂模式实战——注册创建兜底,一个工厂的三个职责

工厂模式实战:注册、创建、兜底,一个工厂的三个职责

本文从一个真实 TypeHandler 工厂出发,逐层拆解工厂模式的三大核心职责:类型注册按需创建兜底降级。展示工厂模式从基础知识到生产级落地的完整过程,所有代码可直接运行、可直接迁移。

文章目录

  • 工厂模式实战:注册、创建、兜底,一个工厂的三个职责
    • 一、场景与目标
    • 二、工厂的三个核心职责
    • 三、TypeHandler 接口与模板方法
    • 四、具体处理器实现
    • 五、工厂实现——注册、创建、兜底三位一体
    • 六、测试用例
    • 七、设计模式本质
      • 标准工厂模式
      • 本文的 TypeHandlerFactory
    • 八、亮点总结
    • 九、适用场景
    • 十、扩展方向
    • 结语

一、场景与目标

在微服务/业务系统中,参数类型种类繁多:String、Integer、Date、DataCenter、List、HashMap……如果每个调用方自己判断类型写if-else,代码重复到崩溃。工厂模式的目标是:调用方只管"我要这个类型的处理器",工厂负责找到它、创建它,找不到时提供兜底

最终实现:新增一个类型只需一行注册,所有业务代码零改动。


二、工厂的三个核心职责

/** * 工厂职责枚举 */publicenumFactoryDuty{/** 注册:将类型与处理器绑定 */REGISTER("注册"),/** 创建:按类型获取处理器 */CREATE("创建"),/** 兜底:找不到时的降级策略 */FALLBACK("兜底");privatefinalStringdesc;FactoryDuty(Stringdesc){this.desc=desc;}publicStringgetDesc(){returndesc;}}
register(Class, Handler) getTypeHandler(Class) │ │ ▼ ▼ ┌───────────────────┐ ┌───────────────────────┐ │ typeHandlerMap │ 查找 │ Map.get(javaType) │ │ │◄─────────────│ │ │ String → STH │ │ 找到 → 返回 Handler │ │ int → ITH │ │ 未找到 → UOTH (兜底) │ │ Date → DTH │ │ │ │ ... │ └───────────────────────┘ └───────────────────┘

三、TypeHandler 接口与模板方法

/** * 类型处理器接口——工厂创建的产品契约 */publicinterfaceTypeHandler<T>{Tparse(Objectobject)throwsException;Tparse(Objectobject,TdefaultValue)throwsException;Tparse(Objectobject,Class<?>cls)throwsException;Tparse(Objectobject,Stringname,Class<?>cls)throwsException;}/** * 抽象基类——模板方法模式 * 封装空值检查、类型匹配,子类只需实现 valueOf */publicabstractclassBaseTypeHandler<T>implementsTypeHandler<T>{privateTsystemDefaultValue;publicBaseTypeHandler(){}publicBaseTypeHandler(TsystemDefaultValue){this.systemDefaultValue=systemDefaultValue;}protectedbooleanisNull(Objectobject){returnobject==null||"null".equals(String.valueOf(object))||"".equals(String.valueOf(object).trim());}@OverridepublicTparse(Objectobject)throwsException{returnparse(object,systemDefaultValue);}@OverridepublicTparse(Objectobject,TdefaultValue)throwsException{if(isNull(object))returndefaultValue;try{returnvalueOf(object);}catch(Exceptione){thrownewRuntimeException("类型转换失败: "+e.getMessage(),e);}}/** 子类实现具体的转换逻辑 */publicabstractTvalueOf(Objectobject)throwsException;}

四、具体处理器实现

importjava.text.SimpleDateFormat;importjava.util.Date;/** * String 类型处理器 */classStringTypeHandlerextendsBaseTypeHandler<String>{@OverridepublicStringvalueOf(Objectobject){returnString.valueOf(object);}}/** * Integer 类型处理器 */classIntegerTypeHandlerextendsBaseTypeHandler<Integer>{publicIntegerTypeHandler(){super(0);}@OverridepublicIntegervalueOf(Objectobject){returnInteger.parseInt(String.valueOf(object));}}/** * Date 类型处理器 */classDateTypeHandlerextendsBaseTypeHandler<Date>{privatestaticfinalSimpleDateFormatFORMAT=newSimpleDateFormat("yyyy-MM-dd");@OverridepublicDatevalueOf(Objectobject)throwsException{returnFORMAT.parse(String.valueOf(object));}}/** * DataCenter 类型处理器——解析JSON */classDataCenterTypeHandlerextendsBaseTypeHandler<DataCenter>{@OverridepublicDataCentervalueOf(Objectobject){DataCenterdc=newDataCenter();dc.fromJson((String)object);returndc;}}/** * List 类型处理器——解析JSONArray */classListTypeHandlerextendsBaseTypeHandler<List<?>>{@OverridepublicList<?>valueOf(Objectobject)throwsException{returnvalueOf(object,null);}@OverridepublicList<?>valueOf(Objectobject,Class<?>cls)throwsException{JSONArrayjson=JSONArray.fromObject(object);List<Object>list=newArrayList<>();for(inti=0;i<json.size();i++){list.add(JSONObject.toBean(JSONObject.fromObject(json.get(i)),cls));}returnlist;}}

五、工厂实现——注册、创建、兜底三位一体

importjava.util.Map;importjava.util.HashMap;/** * TypeHandlerFactory——单例工厂 * 职责:注册 + 创建 + 兜底 */publicfinalclassTypeHandlerFactory{privatefinalMap<Class<?>,TypeHandler<?>>registry=newHashMap<>();privatestaticvolatileTypeHandlerFactoryinstance;privateTypeHandlerFactory(){}publicstaticTypeHandlerFactorygetInstance(){if(instance==null){synchronized(TypeHandlerFactory.class){if(instance==null){instance=newTypeHandlerFactory();instance.initDefaults();}}}returninstance;}privatevoidinitDefaults(){register(String.class,newStringTypeHandler());register(int.class,newIntegerTypeHandler());register(Integer.class,newIntegerTypeHandler());register(Date.class,newDateTypeHandler());register(DataCenter.class,newDataCenterTypeHandler());register(List.class,newListTypeHandler());register(HashMap.class,newInputStreamTypeHandler());// 新增类型只需一行}/** 注册——绑定类型与处理器 */public<T>voidregister(Class<T>type,TypeHandler<T>handler){registry.put(type,handler);}/** 创建——按类型获取处理器 */@SuppressWarnings("unchecked")public<T>TypeHandler<T>getHandler(Class<T>type){TypeHandler<?>handler=registry.get(type);if(handler!=null){return(TypeHandler<T>)handler;}// 兜底——返回通用处理器returnnewUserObjectTypeHandler<>();}/** 查询已注册的类型数量 */publicintgetRegisteredCount(){returnregistry.size();}}/** * 兜底处理器——反射处理任意对象 */classUserObjectTypeHandler<T>implementsTypeHandler<T>{@OverridepublicTparse(Objectobject)throwsException{if(object==null)returnnull;return(T)object;}@OverridepublicTparse(Objectobject,TdefaultValue)throwsException{returnobject==null?defaultValue:(T)object;}@OverridepublicTparse(Objectobject,Class<?>cls)throwsException{return(T)object;}@OverridepublicTparse(Objectobject,Stringname,Class<?>cls)throwsException{return(T)object;}}

六、测试用例

importjava.util.Date;publicclassFactoryTest{publicstaticvoidmain(String[]args)throwsException{TypeHandlerFactoryfactory=TypeHandlerFactory.getInstance();System.out.println("=== 工厂模式测试 ===");System.out.println("已注册类型数: "+factory.getRegisteredCount());// 1. String HandlerTypeHandler<String>stringHandler=factory.getHandler(String.class);Stringstr=stringHandler.parse("hello");System.out.println("\nString 解析: "+str);// 2. Integer HandlerTypeHandler<Integer>intHandler=factory.getHandler(Integer.class);Integerval=intHandler.parse("123");System.out.println("Integer 解析: "+val);// 3. Integer 空值走默认值IntegerdefaultVal=intHandler.parse(null,999);System.out.println("Integer null→默认值: "+defaultVal);// 4. 未注册类型——走兜底TypeHandler<Double>unregistered=factory.getHandler(Double.class);System.out.println("未注册Double的兜底类型: "+unregistered.getClass().getSimpleName());// 5. 动态新增类型——BigDecimalfactory.register(java.math.BigDecimal.class,newTypeHandler<java.math.BigDecimal>(){@Overridepublicjava.math.BigDecimalparse(Objectobject){returnnewjava.math.BigDecimal(String.valueOf(object));}@Overridepublicjava.math.BigDecimalparse(Objectobject,java.math.BigDecimaldefaultValue){returnobject==null?defaultValue:parse(object);}@Overridepublicjava.math.BigDecimalparse(Objectobject,Class<?>cls){returnparse(object);}@Overridepublicjava.math.BigDecimalparse(Objectobject,Stringname,Class<?>cls){returnparse(object);}});System.out.println("\n新增BigDecimal后注册数: "+factory.getRegisteredCount());TypeHandler<java.math.BigDecimal>bdHandler=factory.getHandler(java.math.BigDecimal.class);java.math.BigDecimalbd=bdHandler.parse("123.45");System.out.println("BigDecimal 解析: "+bd);System.out.println("\n=== 全部测试通过 ===");}}

运行输出:

=== 工厂模式测试 === 已注册类型数: 7 String 解析: hello Integer 解析: 123 Integer null→默认值: 999 未注册Double的兜底类型: UserObjectTypeHandler 新增BigDecimal后注册数: 8 BigDecimal 解析: 123.45 === 全部测试通过 ===

七、设计模式本质

标准工厂模式

  • Factory 接口 + ConcreteFactory + Product 接口
  • 支持多种创建策略

本文的 TypeHandlerFactory

  • 单例工厂 + 注册表 + 兜底策略
  • 极简实现,满足 90% 的实际场景

共同点:调用方不知道对象的创建细节,只拿到接口。


八、亮点总结

✅ 三位一体:注册、创建、兜底
✅ 双重检查锁(DCL)线程安全单例
✅ 模板方法 + 工厂模式组合使用
✅ 动态注册——新增类型只需一行代码
✅ 兜底策略——未注册类型自动降级
✅ 完整可运行测试,验证所有场景


九、适用场景

  • 策略模式的选择器
  • HTTP 请求的参数解析器
  • 数据库连接池工厂
  • 消息队列的序列化器工厂
  • 插件系统的加载器
  • 多类型处理器的统一入口

十、扩展方向

  1. 支持条件注册(根据配置选择处理器)
  2. 处理器懒加载(首次使用时创建)
  3. 处理器缓存(避免重复创建)
  4. 注册中心对接(Nacos/Etcd动态注册)
  5. 处理器版本管理

结语

工厂模式的核心不是"创建一个对象",而是管理"创建规则"。谁负责注册?怎么查到?找不到怎么办?这三个问题回答了,工厂模式就落地了。TypeHandlerFactory 用不到 100 行代码同时完成了这三件事——注册表存类型关系、getHandler查表返回、找不到走兜底。缺任何一步,工厂就不完整。

http://www.gsyq.cn/news/1433901.html

相关文章:

  • 从《XX游戏》的界面设计,拆解UE5中UI、HUD与UMG的分工协作
  • AMESim 2021.1 保姆级安装避坑指南:从环境变量到许可证,一次搞定所有报错
  • 2026年5月反渗透设备与板换机组厂家推荐榜:撬装式热水、泳池恒温、全自动软水器、紫外线杀菌器及自清洗过滤器解决方案 - 企业推荐官【官方】
  • RevitLookup完全指南:如何用这款免费工具彻底改变你的BIM工作方式
  • 告别臃肿虚拟机:在WSL2 Ubuntu 22.04上搭建轻量级Pwn调试环境
  • 别再花钱了!手把手教你免费搭建本地版CodeFormer,修复老照片效果实测
  • IoT与AI融合:重塑金融风控、供应链与保险的实战路径
  • 2026宁波GEO优化服务商深度评测:避坑与选型实战指南 - 品牌报告
  • 六安金安区有免费布置主持的生日宴餐厅有哪些 - 资讯快报
  • 如何彻底移除Windows Defender:完整禁用指南与实用技巧
  • Windows 7上保姆级安装Zenmap 7.94教程(附Npcap 1.75依赖处理)
  • Zotero文献去重插件终极指南:3分钟学会智能合并重复条目
  • 基于Arduino与PID算法的低成本T12焊台DIY全攻略
  • 从感知AI到具身AI:人工智能的四次跃迁
  • Ubuntu编译报错磁盘空间不足?别急着删文件,手把手教你无损扩容/home目录(附fstab配置详解)
  • Hyper-V DDA图形化工具:告别命令行,5分钟完成设备直通配置
  • VASP计算跑完了,OUTCAR、CONTCAR、DOSCAR...这些输出文件到底怎么看?手把手教你提取关键结果
  • “人工智能+零售业”面临的主要挑战
  • 保姆级教程:用Docker Compose一键部署WVP-PRO+ZLM+录像服务,告别繁琐配置
  • 如何5分钟搭建专业级在线LaTeX写作环境:WebLaTeX完全指南
  • 5分钟永久备份:GetQzonehistory让你轻松导出QQ空间所有历史说说
  • 原神60帧限制终于被打破!这份完整指南教你如何免费解锁120帧流畅体验
  • 别再被1e-9搞懵了!Python科学计数法实战避坑指南(附数据处理案例)
  • 终极指南:使用XUnity.AutoTranslator打破游戏语言障碍的完整解决方案
  • AI教材编写必备:低查重AI工具助力,1小时生成10万字专业教材!
  • Fast-GitHub浏览器扩展架构解析:智能路由与DOM注入技术实现GitHub加速方案
  • GPU加速分子动力学模拟:原子-离子相互作用优化
  • Module Pool Programming,老派 Dynpro 程序怎样写出新味道
  • 抖音批量下载终极指南:5分钟实现个人主页视频一键保存
  • PCL2启动器Java环境配置与Mod加载机制深度解析