设计模式系列:工厂模式

一、核心概念

工厂模式 = "对象的'生产车间'" 核心逻辑:把 "创建对象" 的活儿,从客户端手里抢过来,交给专门的 "工厂类" 干------ 客户端不用知道对象是怎么 new 出来的、内部逻辑是什么,只要告诉工厂 "我要什么",工厂直接把造好的对象扔给你用。

二、解决的核心痛点(为什么不能直接 new,非要用工厂?)

工厂模式解决 3 个核心问题:

  1. 创建逻辑太复杂,客户端扛不住:如果一个对象创建要写 10 行代码(比如初始化参数、连接资源、校验规则),每个客户端都要写一遍,重复代码爆炸;
  2. 对象类型可能变,改代码改到吐 :比如原来用MySQLConnection,后来要换成OracleConnection,如果所有客户端都直接new MySQLConnection(),得一个个改;
  3. 客户端不需要知道 "怎么造",只需要 "怎么用":你买手机不用知道芯片怎么焊、系统怎么装,店里(工厂)给你成品就行 ------ 对象也一样。

三、核心角色

工厂模式的 4 个核心角色,每个角色各司其职,分工明确:

角色名称 通俗解释(类比现实) 工厂模式中具体例子(Shape 案例)
抽象产品(Abstract Product) 所有产品的 "通用说明书":规定产品必须有哪些功能 Shape接口(规定必须有draw()方法)
具体产品(Concrete Product) 符合说明书的 "具体商品":实现通用功能 CircleRectangleSquare(各自实现draw()
抽象工厂(Abstract Factory) 工厂的 "通用营业执照":规定工厂必须能造哪些产品 (简单工厂没有这个角色,工厂方法 / 抽象工厂才有)比如ShapeFactory接口(规定必须有getShape()方法)
具体工厂(Concrete Factory) 真正的 "生产车间":按说明书造具体商品 ShapeFactory类(实现getShape(),造具体形状)

👉 补充:简单工厂模式没有 "抽象工厂",直接用 "具体工厂" 干所有活(入门款);工厂方法 / 抽象工厂是进阶款,多了 "抽象工厂" 来适配更多产品类型(后面会说)。

四、工作流程

工厂模式的流程比较简单,3 步搞定:

  1. 客户端提需求 :客户端不自己new对象,而是找工厂说 "我要一个圆形(CIRCLE)";
  2. 工厂搞生产 :工厂接收需求,按自己的逻辑(比如判断参数)创建对应的具体产品对象(new Circle());
  3. 客户端直接用 :工厂把造好的对象返回给客户端,客户端只需要调用对象的方法(shape.draw()),完全不管对象是怎么造出来的。

👉 工厂模式流程是:客户端发需求→工厂创建产品→返回产品→客户端使用。

五、代码示例

第一步:定义 "抽象产品"(通用说明书)
复制代码
// 抽象产品:Shape接口(规定所有形状必须能"画")
public interface Shape {
    void draw(); // 通用功能:画自己
}
第二步:定义 "具体产品"(具体商品)
复制代码
// 具体产品1:圆形(符合Shape说明书,实现draw())
public class Circle implements Shape {
    @Override
    public void draw() {
        System.out.println("画了一个圆形");
    }
}

// 具体产品2:矩形(同理)
public class Rectangle implements Shape {
    @Override
    public void draw() {
        System.out.println("画了一个矩形");
    }
}

// 具体产品3:正方形(同理)
public class Square implements Shape {
    @Override
    public void draw() {
        System.out.println("画了一个正方形");
    }
}
第三步:定义 "具体工厂"(生产车间)
复制代码
// 具体工厂:ShapeFactory(负责造所有Shape产品)
public class ShapeFactory {
    // 生产方法:接收需求(形状名称),返回造好的产品
    public Shape getShape(String shapeType) {
        if (shapeType == null) {
            return null; // 没需求,不生产
        }
        // 按需求造对应产品(工厂的核心生产逻辑)
        if (shapeType.equalsIgnoreCase("CIRCLE")) {
            return new Circle();
        } else if (shapeType.equalsIgnoreCase("RECTANGLE")) {
            return new Rectangle();
        } else if (shapeType.equalsIgnoreCase("SQUARE")) {
            return new Square();
        }
        return null; // 没有对应产品
    }
}
第四步:客户端调用
复制代码
public class FactoryDemo {
    public static void main(String[] args) {
        // 1. 拿到工厂
        ShapeFactory shapeFactory = new ShapeFactory();

        // 2. 提需求:要圆形,工厂返回产品(不用自己new Circle())
        Shape circle = shapeFactory.getShape("CIRCLE");
        circle.draw(); // 用产品:画圆形

        // 3. 提需求:要矩形
        Shape rectangle = shapeFactory.getShape("RECTANGLE");
        rectangle.draw(); // 用产品:画矩形

        // 4. 提需求:要正方形
        Shape square = shapeFactory.getShape("SQUARE");
        square.draw(); // 用产品:画正方形
    }
}
运行结果
复制代码
画了一个圆形
画了一个矩形
画了一个正方形

六、工厂模式的 3 个变种

就像责任链有 "单向链、环形链",工厂模式也有 3 个核心变种,核心都是 "创建与使用分离",只是灵活度不同:

变种类型 通俗解释(类比现实) 核心特点 适用场景
简单工厂模式(入门) 一个工厂干所有活:比如 "小作坊",又造圆形又造矩形 没有抽象工厂,逻辑都在具体工厂(像责任链只有一个具体处理器) 产品类型少、变化少(比如只有 3 种形状)
工厂方法模式(进阶) 一个工厂只干一件活:"圆形工厂" 只造圆形,"矩形工厂" 只造矩形 每个具体产品对应一个具体工厂(像责任链每个处理器只处理一种请求) 产品类型多、需要扩展(比如新增三角形,只加 "三角形工厂")
抽象工厂模式(高阶) 一个工厂造 "一套产品":比如 "家电工厂" 造电视 + 冰箱,"手机工厂" 造手机 + 耳机 抽象工厂定义 "造一套产品" 的接口,具体工厂实现整套生产(像责任链处理 "一系列相关请求") 产品是 "成套出现" 的(比如数据库驱动 + 方言、UI 组件套系)

👉 重点:不管哪个变种,核心都没变 ------ 客户端只提需求,工厂负责创建,不用直接new

七、优点 & 缺点

优点
  1. 解耦:创建对象和使用对象分开,客户端不用关心 "怎么造",只关心 "怎么用"(像责任链客户端不用关心 "谁处理");
  2. 易扩展:新增产品时,简单工厂改工厂逻辑,工厂方法 / 抽象工厂只加新工厂 + 新产品,不用改客户端(像责任链加新处理器,不用改客户端);
  3. 易维护 :创建逻辑集中在工厂,要改只改工厂(比如圆形的draw()逻辑变了,只改Circle类,不用改所有客户端)。
缺点
  1. 类变多:工厂方法 / 抽象工厂模式下,一个产品对应一个工厂,类的数量会翻倍
  2. 简单场景没必要 :如果对象很简单(比如new User()就一行),用工厂模式会多一个工厂类,反而增加复杂度(像责任链处理简单请求,没必要搞链路);
  3. 扩展有局限:抽象工厂模式如果要新增 "成套产品" 中的一个(比如家电工厂原本造电视 + 冰箱,现在要加洗衣机),需要改抽象工厂接口,违反开闭原则

八、实际应用场景

工厂模式在开发中很常用,到处都是:

  1. 数据库访问:Hibernate 换数据库时,只改 "数据库工厂" 的配置(MySQL 工厂→Oracle 工厂),不用改业务代码;
  2. 日志框架:日志可以输出到硬盘、控制台、远程服务器,对应 "硬盘日志工厂""控制台日志工厂",客户端选一个就行;
  3. 框架源码 :Spring 的BeanFactory(创建 Bean 对象)、Java 的Calendar.getInstance()(创建日历对象),本质都是工厂模式;
  4. 插件开发:比如 IDE 的插件,每个插件对应一个 "插件工厂",IDE 启动时通过工厂创建插件实例。

九、注意事项

  1. 别过度设计 :简单对象直接new,复杂对象(创建要 3 行以上代码)再用工厂;
  2. 优先选简单工厂 / 工厂方法:大多数场景下,简单工厂(产品少)或工厂方法(产品多)就够了,抽象工厂除非是 "成套产品",否则不用;
  3. 避免工厂逻辑太复杂 :如果工厂里的if-else太多(比如简单工厂有 10 种产品),可以结合责任链或策略模式优化(但这是进阶操作,基础场景不用)。

总结

工厂模式的核心就是 "把创建对象的活儿交给专业的人(工厂)干",本质是 "创建与使用分离"------ 和责任链 "处理请求与发起请求分离" 的思想异曲同工。

记住:能直接new且不麻烦的,就不用工厂;创建逻辑复杂、需要灵活切换的,就用工厂。按这个原则选,永远不会错!

相关推荐
维天说42 分钟前
CLI-Switch 2026年3月版历史设计:Hook、TTY 隔离与 JSON 状态
java·服务器·json
Zane19941 小时前
并发 vs 并行:别再傻傻分不清了,一文讲透 Java 并发编程的第一课
java·后端
杨充2 小时前
11.DDD与战术建模
设计模式·开源·代码规范
杨充2 小时前
12.综合实战图片框架
设计模式·开源·代码规范
噢,我明白了2 小时前
java中Excel的导入和导出(EasyExcel)
java·开发语言·excel
吠品2 小时前
Zabbix Web界面误报Server未运行的排查与解决
java·服务器·数据库
啊湘2 小时前
天气查询API接口 按月Token鉴权 实时天气 物联网可用 文档齐全
java·后端·struts
Java内核笔记3 小时前
告别十亿美元的错误 : Spring Boot 4 空安全 (JSpecify) 实战
java·spring boot·后端
糖果店的幽灵3 小时前
langgraph的 MessagesState 解读
java·开发语言·人工智能·windows·langgraph
谙弆悕博士3 小时前
系统集成项目管理工程师教程(第3版)笔记——第4章:信息系统架构
笔记·系统架构·项目管理·创业创新·学习方法·业界资讯·物理