设计模式与生活②:你只管点外卖,别管堡怎么做

周日上午,小王大扫除。扫地拖地、收拾屋子,一通忙活下来,整个人瘫在沙发上。

然后饿了。

两个选择:自己做饭------买菜、洗菜、切配、掌勺、洗碗,一套下来,一两个小时就没了;或者打开外卖 App,点一份"麦辣鸡腿堡"。

他选了后者。三十分钟后,饭到了。

大扫除后的哲学家:能不下厨,就不下厨

这半小时里他没进厨房,不知道鸡腿肉是谁裹粉炸的、油温烧到多少度、酱料挤了几泵。他只管"要什么",不管"怎么造"。

今天聊的,就是这件事在代码里的样子:工厂模式(Factory Pattern)------把"造对象"这件事,从"用对象"的人手里拿走。系列第二篇,从小王这顿外卖开始。

01 · 自己 new,就是自己下厨

代码里的"自己下厨",长这样:

java 复制代码
// 想吃麦辣鸡腿堡,自己 new:备料、腌制、油炸、组装全包
Meal meal = new McSpicyBurger("芝麻包", "炸鸡腿肉", "双倍辣酱");

// 构造器改一个参数,所有"自己下厨"的地方都得跟着改

自己 new:调用方和后厨死绑

想吃这个堡,你得先拿到配方:鸡腿肉腌多久、裹多厚的粉、油温烧到多少度------构造器的每个参数你都得懂。哪天 McSpicyBurger 改了构造签名,所有自己 new 过它的地方,全部跟着改。

一个类被 new 了一百次,就长出一百根绳子,把一百个调用方和它捆死在一起。

02 · 简单工厂:你报名字,后厨来做

麦当劳的做法,是把"怎么做"收进后厨。你只管报名字:

java 复制代码
public class MealFactory {

    // 后厨:你报名字,它来做
    public static Meal create(String name) {
        switch (name) {
            case "麦辣鸡腿堡": return new McSpicyBurger();
            case "板烧鸡腿堡": return new GrilledChickenBurger();
            case "巨无霸": return new BigMac();
            default: throw new IllegalArgumentException("这款堡不会");
        }
    }
}

// 你只管点,后厨的事不操心
Meal meal = MealFactory.create("麦辣鸡腿堡");

简单工厂:名字进,对象出

调用方从此不认识 McSpicyBurger,只认识两样东西:菜单(Meal 接口)和这家店(MealFactory)。创建和使用,分家了。

左边是你点外卖,右边是简单工厂

得挑明一个类比的失真点:点外卖会踩雷------图片上的堡又大又挺,到手就瘪了;代码里的工厂不会缩水,它返回的对象一定满足接口约定,说是什么就是什么。代码里的后厨,比外卖店守信用。

再问一步:菜单越写越长,会怎样?

03 · 工厂方法:一款汉堡,开一条产线

菜单从 3 款加到 30 款,后厨那个 switch 就写出 30 个分支。更要命的是:每上一款新品,都得改后厨------改错一行,全店停业。

这撞上了设计里的一条铁律:对扩展开放,对修改关闭。

解决办法:一款汉堡,开一条专属产线。 总部只定规矩------是条产线就得会出堡;具体做哪款,各产线自己说了算:

java 复制代码
// 总部定的规矩:是条产线,就得会出堡
interface BurgerLine {
    Meal cook();
}

// 麦辣鸡腿堡产线
class McSpicyLine implements BurgerLine {
    public Meal cook() {
        return new McSpicyBurger();
    }
}

// 板烧鸡腿堡产线
class GrilledLine implements BurgerLine {
    public Meal cook() {
        return new GrilledChickenBurger();
    }
}

工厂方法:上新品 = 新拉产线,老线不动

上新品 = 新拉一条产线,老产线的按钮一个不动。这就是工厂方法(Factory Method):把"造哪个"的决定,推迟给子类。

再问一步:光一个堡,够吗?

04 · 抽象工厂:套餐,讲究的是一整套配套

小王后来不点单品了,改点套餐。套餐的讲究不在单个堡,在搭配:麦当劳套餐配可口可乐,肯德基套餐配百事可乐------两大阵营签的都是排他协议,混不了。

配套不能错------麦当劳的杯子里倒出百事可乐,店员自己先慌了。

**抽象工厂(Abstract Factory)**管的,就是这一整套配套:

java 复制代码
// 套餐工厂:一整套搭配,保证不串味
interface ComboFactory {
    Burger burger();    // 堡
    Fries fries();      // 薯条
    Drink drink();      // 可乐
}

// 麦当劳套餐
class McDonaldsCombo implements ComboFactory {
    public Burger burger() { return new McSpicyBurger(); }
    public Fries fries()   { return new McFries(); }
    public Drink drink()   { return new Coke(); }
}

// 肯德基套餐
class KfcCombo implements ComboFactory {
    public Burger burger() { return new ZingerBurger(); }
    public Fries fries()   { return new KfcFries(); }
    public Drink drink()   { return new Pepsi(); }
}

抽象工厂:换套餐 = 换工厂,整套一次换

三种工厂讲完,一张图收个尾:

一家店 → 专门店一条街 → 套餐档口

05 · 这些"后厨",你天天在用

  • 📅 JDK 的 Calendar.getInstance():你不管它背后是公历还是佛历,拿来就用------简单工厂的思路;
  • 🔢 Integer.valueOf():《Effective Java》第 1 条就劝你:优先考虑静态工厂方法,别上来就 new;
  • 📋 SLF4J 的 LoggerFactory.getLogger():你只管要个 logger,背后是 Logback 还是 Log4j2,不用你操心;
  • 🌱 Spring 整个容器就是个超级大工厂:BeanFactory / ApplicationContext,你声明要什么 Bean,它负责造。

06 · 什么时候,别建工厂

说点边界。还是那个周日------小王擦桌子,拿块抹布蘸水就擦了。他不会为擦桌子先定义 CleaningTool 接口、写个 RagFactory、再 create 一块抹布出来。

自己就煎个蛋,犯不上先拉一条产线。

判断标准就一条:创建这件事,复杂吗?会变吗?

构造器一长串参数、创建要读配置、连资源、攒依赖------值得建工厂;

new ArrayList<>() 这种一行搞定、十年不变的------直接 new,别套。

工厂模式最常被骂的滥用,就是给每个类都配个工厂,类数量翻倍,读代码像剥洋葱。模式是工具,不是奖状------用了不涨工资。

最后跟系列第一篇呼应一下:工厂只管"怎么造",不管"造几个"。点两次外卖来两份,天经地义;想让全系统只有一份,那是单例的活,别混。

带走一句话:工厂模式 = 把"怎么做"关进后厨------你只管报名字(接口),做堡(new)的事,工厂包了。

好的代码和好的外卖一样:你享受结果,不必进厨房。

参考资料

  1. Erich Gamma 等,《设计模式:可复用面向对象软件的基础》(GoF 原著)------工厂方法、抽象工厂的原始出处
  2. 《Head First 设计模式》第 4 章------用披萨店讲工厂,本文"外卖店"类比的同乡
  3. Joshua Bloch,《Effective Java(第 3 版)》------第 1 条:考虑用静态工厂方法代替构造器(本文反例段的依据)
  4. Spring 官方文档 · IoC 容器
相关推荐
是2的10次方啊19 小时前
设计模式与生活①:你的脸,为什么不能有第二个?
设计模式
高晶21 小时前
ARM 嵌入式 Linux 命令系统 BusyBox 实战指南
linux·设计模式·程序员
高晶21 小时前
语音合成与变声技术十大业务场景落地实战:从电商直播到规模化生产
设计模式·程序员
博风1 天前
19、设计模式应用举例:桥接模式:制作电视节目
设计模式·桥接模式
知守观1 天前
从 4 套 PDF 库的混战,聊聊老项目的依赖管理与“静默失败”
java·后端·设计模式
geovindu2 天前
rust: Mediator Pattern
开发语言·后端·设计模式·rust·中介者模式·行为模式
SENKS_DIGITAL2 天前
金属加工遇上数字化:通快展厅里的工业蜕变-森克思科技
科技·设计模式·展厅设计·展馆设计·科技展厅设计·展览设计·企业展厅设计
flower9803232 天前
C++消息总线软件开发框架AI重构版
c++·设计模式·架构
zzu123zsw3 天前
业务拆分后的治理深水区:解构企业级微服务六大核心设计模式与高可用落真实践
微服务·设计模式·架构·高可用·微服务架构设计