让代码变美的第四天 - 工厂方法模式

Visual Studio 2013 + Intel(R) Visual Fortran 安装教程 安装了好几遍,ivf都不能加载到vs中,中途放弃了vs,又改用codeblocks编译器,依然在写fortran的时候出现了各种问题,于是又放弃了codeblocks改回vs,总之是折腾了好久,终于装明白了ivf并且将fortran模板成功加载到vs中。 PS:一定要安装Intel Visual Fortran.Composer XE.2013-SP1,不要用Intel Visual Fortr... 阅读详情

话接上回【让代码变美的第三天 - 简单工厂模式】
简单工厂其实还是不够完美,破坏了程序的开放封闭,那么看下工厂方法模式如何解决

丑陋的模样

简单工厂代码

    public static Fruit getFruit(String name) {
        if ("苹果".equals(name)) {
            Apple apple = new Apple();
            // 洗苹果 + 切苹果
            // todo other init
            return apple;
        } else if ("菠萝".equals(name)) {
            Pineapple pineapple = new Pineapple();
            // 切菠萝
            // todo other init
            return pineapple;
        } else {
            throw new RuntimeException("没有找到该水果");
        }
    }

重构

抽象工厂

public interface FruitFacory {
    Fruit getFruit();
}

定义具体工厂

public class AppleFacory implements FruitFacory {
    @Override
    public Fruit getFruit() {
        Apple apple = new Apple();
        // 洗苹果 + 切苹果
        // todo other init
        return apple;
    }
}
public class PineappleFacory implements FruitFacory {
    @Override
    public Fruit getFruit() {
        Pineapple pineapple = new Pineapple();
        // 切菠萝
        // todo other init
        return pineapple;
    }
}

使用

    public void sendApple() {
        AppleFacory appleFacory = new AppleFacory();
        Fruit apple = appleFacory.getFruit();
//        Fruit apple = FruitFacory.getFruit("苹果");
        sendPeople(apple);
    }

    public void eatApple() {
        AppleFacory appleFacory = new AppleFacory();
        Fruit apple = appleFacory.getFruit();
//        Fruit apple = FruitFacory.getFruit("苹果");
        eatPeople(apple);
    }

    public void eatPineapple() {
        AppleFacory appleFacory = new AppleFacory();
        Fruit pineapple = appleFacory.getFruit();
//        Fruit pineapple = FruitFacory.getFruit("菠萝");
        eat(apple);
    }

注释掉的是简单工厂的获取方式,可以简单进行对比,工厂方法模式无非就是对每个产品包装了一层,这一层就是具体的工厂
UML图(网上借用的)如下:
网上借用的图

新问题

每次获取产品的时候,都要精确知道是哪个工厂生产的,不管要记住产品的名字,还要记住工厂的名字,这不是给工作增加负担么?
有没有一种办法,使得客户不用关心具体是哪个工厂生产的呢?就和简单工厂模式一样简单呢?

再次重构

只讨论JAVA场景,Spring项目,利用Spring优雅的解决上面的问题。
其实在【让代码变美的第一天 - 观察者模式】中也是使用类似这种办法。
重新定义产品名(简单工厂中使用的产品名)

public interface FruitFacory {
    String getFruitName();

    Fruit getFruit();
}
@Component
public class AppleFacory implements FruitFacory {
    @Override
    public Fruit getFruit() {
        Apple apple = new Apple();
        // 洗苹果 + 切苹果
        // todo other init
        return apple;
    }

    @Override
    public String getFruitName() {
        return "苹果";
    }
}
@Component
public class PineappleFacory implements FruitFacory {
    @Override
    public Fruit getFruit() {
        Pineapple pineapple = new Pineapple();
        // 切菠萝
        // todo other init
        return pineapple;
    }

    @Override
    public String getFruitName() {
        return "菠萝";
    }
}
  • 产品名也可以使用【让代码变美的第一天 - 观察者模式】中的注解来实现,注解或许x格高一点。

构建产品名和工厂的映射关系

@Service
public class FruitService {
    public static Map<String, FruitFacory> fruitFactoryMap = new HashMap<>();

    @Autowired
    private List<FruitFacory> fruitFactoryList;

    @PostConstruct
    private void init() {
        for (FruitFacory fruitFacory : fruitFactoryList) {
            fruitFactoryMap.put(fruitFacory.getFruitName(), fruitFacory);
        }
    }

    public static Fruit getFruit(String fruitName) {
        return fruitFactoryMap.get(fruitName).getFruit();
    }
}

使用

    public void sendApple() {
        Fruit apple = FruitService.getFruit("苹果");
//        AppleFacory appleFacory = new AppleFacory();
//        Fruit apple = appleFacory.getFruit();
//        Fruit apple = FruitFacory.getFruit("苹果");
//        sendPeople(apple);
    }

    public void eatApple() {
        Fruit apple = FruitService.getFruit("苹果");
//        AppleFacory appleFacory = new AppleFacory();
//        Fruit apple = appleFacory.getFruit();
//        Fruit apple = FruitFacory.getFruit("苹果");
//        eatPeople(apple);
    }

看这里是不是又和简单工厂模式差不多了,外部不用关心产品内部细节,也不需要关心需要用哪个工厂,只要通过名称获取到产品即可
再来看有没有破坏开放封闭原则,我们新增一个产品,比如:香蕉。

  • 只需要新增Banana(产品)、BananaFacory(工厂)。

Spring帮我们解决的是扫描所有工厂类(当然我们自己利用反射也能做),让我们无需在新增工厂的时候去加if else

实现真正的「人机」对战:引入三方 AI 引擎 引入三方 AI 引擎 前边,我们实现了与云库对战的象棋游戏。这一节中,我们将开始实现真正的「人机」对战 — 人与手机 AI 之间对弈; 实现一套象棋 AI 工程浩大,这个工作我们后续文章会做一番介绍。现代软件工程并不主张每个人都「造轮子」,因此我们要有「站在巨人肩膀上」的小智慧。 本节概要 从 github 寻找开源中象引擎 梳理引擎接入的思路 寻找适合的开源中国象棋引擎 github 上有大... 阅读详情

相关推荐

语音识别(ASR)-- Kaldi 学习笔记

语音识别(ASR)-- Kaldi学习笔记语音识别简介GMM-HMM基本原理DNN-HMM(基于神经网络)KaldiKaldi架构简介Kaldi在Windows下的安装工具准备编译OpenFST配置PortAudio配置KaldiKaldi目录说明 语音识别简介 语音识别(Speech Recognition)技术,也被称为自动语音识别(Automatic Speech Recognition, ASR)、计算机语音识别(Computer Speech Recognition)或是语音转文本识别(Spee

qq_43318971的博客 4847

让代码变美的第三天 - 简单工厂模式

日常重构代码

帅东's Blog 6万+

《AFSim 2.9中文参考手册》

本栏目将对《AFSim 2.9中文参考手册》进行持续更新,欢迎关注交流!对本文或者AFSIM相关内容感兴趣的朋友,可私心联系作者。《AFSim 2.9中文参考手册》内容概览。

henggesim的博客 1万+

13、设计模式应用举例:工厂方法模式:创建药品对象

本文基于工厂方法模式设计药店药品系统,定义抽象产品Drug及具体子类Paracetamol、Amorolfine,通过DrugCreator接口与具体创建者ParaDrugCreator、AmorDrugCreator实现对象的延迟创建。药店应用仅调用工厂方法获取药品实例,避免直接调用构造函数,确保成分信息由药厂提供,符合开闭原则,提升系统可扩展性与职责分离。

博风_刺耳的博客(网络记事本) 267

VIVADO & VITIS 报错记录

问题详情:使用BD用DMA上传少量数据,根据ILA监测到的AXI总线数据正常,VALID信号和READY信号都正常,但是在PS端的cache缓冲区示数为0,打印为0。可能是因为print和printf混用导致。解决方案:修改缓冲区的对齐参数。

Mulun_Zhu的博客 715

【HarmonyOS】ArkUI的组件扩展

ArkuI的组件扩展主要是通过等装饰器来对于一些常用的自定义组件进行封装, 来简化UI开发流程, 提高自定义组件的可复用性。

2302_79763237的博客 1166

【FDE知识库】(1):AI 编程时代开发语言选型分析,云使用go,企业用java,算法python,底层c

AI 编程时代,开发语言选型需综合考量AI适配度、编译速度、跨平台与学习成本。Python以海量语料和即时执行成首选,适用于AI/ML与原型开发;TypeScript凭借类型系统与秒级构建,成为前端及应用层主流;Go以极速编译与统一风格,契合AI代理高效迭代需求。Rust/C++虽性能强,但编译慢、学习成本高,不适于快速试错。综合推荐:优先选Python、TypeScript、Go,兼顾效率与生态,实现最优AI协作体验。

freewebsys的专栏 504

易康eCognition9.0分类|规则集和机器学习的方法的面向对象的多尺度分割分类

基于易康eCognition9.0软件的规则集和机器学习的方法的面向对象的多尺度分割分类

weixin_46493028的博客 1万+

Spring AI + GPT-5.5 + Ollama 配置教程:Base URL、超时与流式调用

由于不同 Spring AI、Spring Boot 小版本之间仍可能存在差异,创建项目时应检查 Spring Initializr、Spring AI BOM 和官方兼容矩阵,不要直接复制旧教程中的 Starter 名称和版本号。多人项目最好隔离不同客户端,并在脱敏前提下记录最终 URL、状态码、请求耗时、请求 ID 和模型 ID。Spring AI 接入模型 API,至少要同时确认 Starter、Base URL、请求路径、API Key、模型 ID、连接超时、读取超时和流式客户端这 8 项。

2601_95893075的博客 223

C++ 工程实践(9):数据抽象

陈硕 (giantchen_AT_gmail)http://blog.youkuaiyun.com/Solstice  http://weibo.com/giantchen陈硕关于 C++ 工程实践的系列文章: http://blog.youkuaiyun.com/Solstice/category/8

陈硕的Blog 1万+

SoIC、CoWoS、InFO一次讲透:从2D/2.5D/3D看懂先进封装

先进封装是后摩尔时代提升芯片性能的关键路径,但面对SoIC、CoWoS、InFO这些名词,很多人容易混淆。理解它们,需从最基本的2D、2.5D、3D封装概念入手:2D是传统平房,2.5D通过硅中介层实现高密度互连,3D则让芯片直接堆叠。CoWoS作为2.5D中介层封装,已成为AI芯片与HBM高带宽存储集成的行业标准;SoIC通过铜-铜混合键合实现真正的3D堆叠,为逻辑与缓存提供极致带宽;InFO以扇出型封装兼顾成本与集成度,广泛用于移动SoC。在系统级封装(SiP)和CPO共封装光学等前沿趋势中,这些技术往

weixin_42388898的博客 310

【JVM】对象内存布局

HotSpot JVM 中,Java 对象内存布局由对象头(12字节,含Mark Word与压缩Klass Pointer)、实例数据及对齐填充构成,总大小为8字节倍数。对象头支持锁状态动态复用,指针压缩使引用仅4字节,但堆超32GB时失效。实例字段按类型优先级重排序以减少间隙,最小对象大小为16字节。通过JOL工具可精准验证布局,理解锁机制、GC、伪共享等底层行为。

2301_79732484的博客 149

我装了10个ClawHub技能,这些最好用!

ClawHub就是Clawdbot的"应用商店"。Clawdbot是手机ClawHub是App Store技能就是各种App装了技能,Clawdbot才能干更多事。这个技能解决了我的信息过载问题。为什么装我订阅了很多Newsletter。每天收到一堆长文章,根本看不完。怎么用“总结这篇文章的核心观点”“把这个Newsletter提炼成3个要点”“这篇技术博客有哪些可以实践的建议?安装命令真实体验现在我收到长文章,直接转发给Clawdbot。它会提炼出核心要点和行动清单。

Maynor的博客 6099

V8 机制、手写核心函数与 TypeScript 类型体操

或固定初始化(如数组先定长、对象先给全字段)保持类型与形状稳定;这些都比"换框架"更基础。只能处理纯数据(丢函数、Date、RegExp、循环引用报错)。生产级深拷贝要处理:原始值短路、循环引用、V8(Chrome / Node 的 JS 引擎)不是"解释一行跑一行"那么简单,它用。图:V8 执行流程——解释执行 + 热点优化,优化失败会 Deopt 回退。JS 内存自动管理,但"自动"不等于"不会漏"。是"固定间隔最多执行一次"。手写 Promise 是"懂异步"的试金石。是"停下后才执行最后一次",

qq_38468358的博客 328

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

Spring Boot 数据源与 MyBatis(-Plus) 自定义配置详解

本文详解 Spring Boot 中单数据源环境下 HikariCP 与 MyBatis-Plus 的自定义配置。通过手动声明 SqlSessionFactory,实现下划线转驼峰、日志输出、一级缓存策略等精细化控制。结合 HikariCP 核心参数调优(如最大连接数、连接生命周期),确保高性能与稳定性。适用于仅需访问单一数据库的场景,避免多数据源复杂性,兼顾性能与可维护性。

BADAO_LIUMANG_QIZHI的博客 195

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Java EE 进阶:8.MyBatis 操作数据库(入门)(第一弹)

Java EE 进阶:8.MyBatis 操作数据库(入门)(第一弹)

要努力去发光,而不是被照亮~ 117

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

LeetCode Hot 100 二叉树专题(二)3 题(Java)

本篇文章共 3 题:543. 二叉树的直径、102. 二叉树的层序遍历、108. 将有序数组转换为二叉搜索树。 每道题都统一按「① 题目分析 & 解题思路 → ② 常见解法(附代码)及讲解 → ③ 知识点总结」的顺序组织;代码使用 Java 编写,节点定义沿用 LeetCode 默认的 TreeNode。

2401_88612756的博客 365

Decorator

TaskDecorator 是异步场景下"跨线程传递上下文"的标准方案,主要用于传递 MDC、用户信息、数据源路由等上下文数据,核心价值是让异步任务的日志链路不中断、业务上下文不丢失。TaskDecorator 是 Spring 提供的一个钩子接口,用于在异步任务执行前对 Runnable 进行包装,常用于跨线程传递上下文。如果你在项目中遇到具体的异步上下文传递问题,可以把代码贴出来,我帮你给出最合适的 Decorator 方案 👍。✅ 核心能力:在线程切换时,把"父线程的上下文"搬到"子线程"

wlwork66的博客 104

JDK 下载安装:装完 Java 提示「不是内部或外部命令」?环境变量没配

JDK 是写 Java 程序必须装的东西。它包含运行 Java 的虚拟机(JRE)和编译 Java 的编译器(javac)——装了它,能跑、.java文件能编译成可执行程序。免费,学习和小规模生产都不花钱。

科小怪的博客 626

数据库乐观锁深度解析:MySQL、PostgreSQL 实战 + Spring Boot 集成指南

Oracle 提供了ORA_ROWSCN伪列(System Change Number),记录最后修改行的 SCN,类似 PostgreSQL 的xmin。实践中通常仍使用 version 字段方案,逻辑与 MySQL 完全相同。-- Oracle:通过 ORA_ROWSCN 实现乐观锁-- 更新时比对 SCN// 自定义注解// AOP 切面@Aspect@Component@Slf4jtry {

yjc_1111的专栏 397

C++ 多态详解:作用、原理与实战用法

多态是C++面向对象的核心特性,通过虚函数实现运行期动态绑定,使同一接口在不同对象上表现出不同行为。其核心作用包括统一接口、提升可扩展性、降低耦合、支持运行时分派与批量处理。实现依赖虚函数表(vtable)和虚指针(vptr),需注意虚析构函数、对象切片等陷阱。相比编译期多态(模板),运行期多态灵活性高但有调用开销。合理结合两者,可兼顾代码的灵活性与性能,是构建可扩展、低耦合系统的关键。

2402_85743155的博客 377

java框架大全

java框架大全

qq_39326137的博客 183

Java 多态 学习笔记

多态是面向对象编程的重要特性,指同一操作作用于不同对象时产生不同行为。其核心在于“父类引用指向子类对象”,结合方法重写实现运行时动态绑定。多态使代码更灵活、可扩展,如用Person p = new Student();统一处理各类人员注册,无需修改调用逻辑。但多态无法直接调用子类特有方法,需通过instanceof判断并强制转换。编译时看左边(类型),运行时看右边(实际对象),实现解耦与维护便利。

AA_AA114514的博客 351

SecureRandom做随机源,这个Java随机字符串工具类有3个方法

本文分享一款JDK17环境下的Java随机字符串工具类,内置3个开箱即用的方法,全部采用SecureRandom加密安全随机源,不存在弱随机、可预测、取模偏差等问题。工具类支持默认62字符集随机串、纯数字随机串、自定义字符集随机串三种生成模式,支持Unicode码点级别的字符集处理,兼容Emoji等增补字符,边界处理严格,异常信息明确,适合验证码、邀请码、盐值、随机口令、短链码等场景,源码可直接复制使用。

Java后端 | AI智能体应用实战派 | 电脑技能行家 295

Java实现批量线段相交检测(跨积判定+扫描线优化与踩坑复盘)

【代码】Java实现批量线段相交检测(跨积判定+扫描线优化与踩坑复盘)

m0_64476639的博客 319

ubuntu安装hadoop系统

本文详细介绍了基于VMware克隆虚拟机搭建三节点Hadoop分布式集群的全过程:使用同一Ubuntu镜像克隆出master、worker1、worker2三台虚拟机,依次配置主机名、固定IP(如192.168.82.10/11/12)、SSH服务及免密登录,确保节点间网络互通。随后安装Java,下载配置Hadoop并分发至各节点,最终初始化启动集群,验证其存储与计算功能,实现高效的大数据环境部署。

qq_43592674的博客 322
上一篇: 让代码变美的第三天 - 简单工厂模式
下一篇: ES如何提高召回率之【词干提取】
帅东
博客等级 码龄11年 676粉丝 88原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值