设计模式之工厂模式:对象创建的智慧之道

工厂模式:对象创建的智慧之道

引言:为什么我们需要工厂模式?

在软件开发中,对象创建是最常见的操作之一 。当代码中充满new关键字时,系统会面临三大痛点:

  1. 紧耦合:客户端代码直接依赖具体实现类
  2. 扩展困难:新增产品类型需修改多处代码
  3. 职责混乱:业务逻辑与对象创建逻辑混杂

工厂模式(Factory Pattern)正是解决这些问题的创建型设计模式 。它通过定义对象创建接口,让子类决定实例化哪个类,实现创建逻辑与使用逻辑的解耦

工厂模式家族包含三种形态:简单工厂工厂方法抽象工厂,各自解决不同层次的问题。


一、简单工厂模式(静态工厂)

1.1 基础概念

classDiagram class Client class SimpleFactory { +createProduct(String type) Product } interface Product { +use() } class ConcreteProductA class ConcreteProductB Client --> SimpleFactory SimpleFactory ..> Product Product <|.. ConcreteProductA Product <|.. ConcreteProductB

1.2 代码实现

java 复制代码
// 产品接口
interface Button {
    void render();
}

// 具体产品
class WindowsButton implements Button {
    public void render() {
        System.out.println("渲染Windows风格按钮");
    }
}

class MacOSButton implements Button {
    public void render() {
        System.out.println("渲染MacOS风格按钮");
    }
}

// 简单工厂
class ButtonFactory {
    public static Button createButton(String osType) {
        if ("windows".equalsIgnoreCase(osType)) {
            return new WindowsButton();
        } else if ("macos".equalsIgnoreCase(osType)) {
            return new MacOSButton();
        }
        throw new IllegalArgumentException("未知操作系统类型");
    }
}

// 客户端调用
public class Client {
    public static void main(String[] args) {
        Button btn = ButtonFactory.createButton("macos");
        btn.render(); // 输出:渲染MacOS风格按钮
    }
}

1.3 适用场景与局限

适用场景

  • 产品种类有限且固定
  • 客户端不关心创建细节

缺点

  • 违反开闭原则(新增产品需修改工厂)
  • 工厂类职责过重

二、工厂方法模式(多态工厂)

2.1 核心思想

classDiagram class Client interface Factory { +createButton() Button } class WindowsFactory class MacOSFactory interface Button class WindowsButton class MacOSButton Client --> Factory Factory <|.. WindowsFactory Factory <|.. MacOSFactory Factory ..> Button Button <|.. WindowsButton Button <|.. MacOSButton

2.2 代码实现

java 复制代码
// 抽象工厂
interface GUIFactory {
    Button createButton();
    Checkbox createCheckbox();
}

// 具体工厂
class WindowsFactory implements GUIFactory {
    public Button createButton() {
        return new WindowsButton();
    }
    public Checkbox createCheckbox() {
        return new WindowsCheckbox();
    }
}

class MacOSFactory implements GUIFactory {
    public Button createButton() {
        return new MacOSButton();
    }
    public Checkbox createCheckbox() {
        return new MacOSCheckbox();
    }
}

// 客户端代码
public class Application {
    private Button button;
    private Checkbox checkbox;
    
    public Application(GUIFactory factory) {
        button = factory.createButton();
        checkbox = factory.createCheckbox();
    }
    
    public void render() {
        button.render();
        checkbox.render();
    }
}

// 使用示例
public class Demo {
    public static void main(String[] args) {
        GUIFactory factory;
        if (System.getProperty("os.name").contains("Windows")) {
            factory = new WindowsFactory();
        } else {
            factory = new MacOSFactory();
        }
        
        Application app = new Application(factory);
        app.render();
    }
}

2.3 模式优势

  1. 完全符合开闭原则:新增产品只需添加新工厂
  2. 单一职责原则:每个工厂只负责一类产品
  3. 可测试性:可通过Mock工厂进行单元测试

三、抽象工厂模式(产品族工厂)

3.1 解决复杂产品族创建

classDiagram class Client interface AbstractFactory { +createButton() Button +createCheckbox() Checkbox } class ModernFactory class VintageFactory interface Button interface Checkbox class ModernButton class VintageButton class ModernCheckbox class VintageCheckbox Client --> AbstractFactory AbstractFactory <|.. ModernFactory AbstractFactory <|.. VintageFactory AbstractFactory ..> Button AbstractFactory ..> Checkbox Button <|.. ModernButton Button <|.. VintageButton Checkbox <|.. ModernCheckbox Checkbox <|.. VintageCheckbox

3.2 跨平台UI案例

java 复制代码
// 抽象产品族
interface Button {
    void render();
}

interface Checkbox {
    void toggle();
}

// 现代风格产品
class ModernButton implements Button {
    public void render() {
        System.out.println("渲染扁平化按钮");
    }
}

class ModernCheckbox implements Checkbox {
    public void toggle() {
        System.out.println("切换Material Design复选框");
    }
}

// 复古风格产品
class VintageButton implements Button {
    public void render() {
        System.out.println("渲染拟物化按钮");
    }
}

class VintageCheckbox implements Checkbox {
    public void toggle() {
        System.out.println("切换复古风格复选框");
    }
}

// 抽象工厂
interface UIFactory {
    Button createButton();
    Checkbox createCheckbox();
}

// 具体工厂
class ModernUIFactory implements UIFactory {
    public Button createButton() {
        return new ModernButton();
    }
    public Checkbox createCheckbox() {
        return new ModernCheckbox();
    }
}

class VintageUIFactory implements UIFactory {
    public Button createButton() {
        return new VintageButton();
    }
    public Checkbox createCheckbox() {
        return new VintageCheckbox();
    }
}

// 配置类(决定使用哪种风格)
class UIStyleConfig {
    public static UIFactory getFactory(String style) {
        if ("modern".equals(style)) {
            return new ModernUIFactory();
        } else if ("vintage".equals(style)) {
            return new VintageUIFactory();
        }
        throw new IllegalArgumentException("未知UI风格");
    }
}

3.3 模式特点

优势

  • 保证产品族兼容性(如统一风格的UI组件)
  • 切换产品族只需替换工厂实例

局限性

  • 新增产品类型需修改所有工厂接口
  • 类数量指数级增长(产品族×产品类型)

四、三大工厂模式对比

特性 简单工厂 工厂方法 抽象工厂
创建对象范围 单一产品 单一产品 产品族
开闭原则支持 ❌ 修改工厂类 ✅ 扩展新工厂 ✅ 扩展新工厂
复杂度 ★☆☆ 简单 ★★☆ 中等 ★★★ 复杂
适用场景 固定类型产品 单一类型产品扩展 相关产品组成的家族
系统扩展方向 垂直扩展(修改代码) 水平扩展(新增工厂) 水平扩展(新增产品族)

五、工厂模式在框架中的实践

5.1 JDK中的工厂模式

java 复制代码
// 工厂方法示例
Calendar cal = Calendar.getInstance(); // 根据时区创建实例

// 抽象工厂示例
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();

5.2 Spring框架的工厂应用

java 复制代码
// BeanFactory:顶级工厂接口
BeanFactory factory = new ClassPathXmlApplicationContext("beans.xml");
MyService service = factory.getBean(MyService.class);

// FactoryBean:定制复杂对象创建
public class MyFactoryBean implements FactoryBean<Connection> {
    public Connection getObject() {
        return DriverManager.getConnection(...);
    }
}

5.3 Log4j2的日志工厂

java 复制代码
Logger logger = LogManager.getLogger(); // 获取日志器工厂

六、工厂模式最佳实践

6.1 何时使用工厂模式?

  1. 系统需要支持多种实现变体(如不同数据库驱动)
  2. 需要隔离创建逻辑与业务代码
  3. 需要统一管理对象生命周期
  4. 实现可插拔架构(运行时切换实现)

6.2 设计原则落地

  • 开闭原则:通过扩展而非修改增加功能
  • 依赖倒置:依赖抽象而非具体实现
  • 单一职责:创建逻辑与业务逻辑分离

6.3 避免常见误区

  1. 过度设计 :简单场景直接使用new
  2. 工厂膨胀:当产品类型过多时考虑重构
  3. 循环依赖:工厂之间避免相互调用

七、工厂模式演进与变种

7.1 静态工厂方法

java 复制代码
// JDK中的经典案例
List<String> list = Collections.unmodifiableList(originalList);

7.2 参数化工厂

java 复制代码
class VehicleFactory {
    Vehicle createVehicle(VehicleType type, String model) {
        switch(type) {
            case CAR: return new Car(model);
            case TRUCK: return new Truck(model);
        }
    }
}

7.3 延迟初始化工厂

java 复制代码
class LazyFactory {
    private Map<String, Product> cache = new HashMap<>();
    
    Product getProduct(String key) {
        if (!cache.containsKey(key)) {
            cache.put(key, createProduct(key));
        }
        return cache.get(key);
    }
}

八、工厂模式经典面试题

Q1:工厂方法和抽象工厂的核心区别?

答案

  • 工厂方法关注单一产品的创建
  • 抽象工厂关注相关产品族的创建
  • 抽象工厂通常包含多个工厂方法

Q2:Spring中的BeanFactory和FactoryBean有何不同?

答案

BeanFactory FactoryBean
基础IoC容器 创建复杂对象的工厂接口
管理所有Bean的生命周期 定制特殊Bean的创建过程
通过getBean()获取对象 实现getObject()返回目标对象

结语:工厂模式的价值思考

工厂模式不仅是技术实现,更是架构思维的体现。它教会我们:

  1. 解耦的艺术:分离变与不变的部分
  2. 扩展的智慧:通过组合而非修改扩展系统
  3. 抽象的边界:合理划分职责边界

在微服务和云原生时代,工厂模式演变为:

  • 依赖注入:更高级的对象装配方式
  • 服务工厂:动态服务实例创建(如gRPC)
  • 云资源工厂:按需创建云资源(AWS/Aliyun SDK)

最后提醒: 不要为了模式而模式!当创建逻辑确实存在变体时,再引入工厂模式。

相关推荐
浮游本尊40 分钟前
Java学习第22天 - 云原生与容器化
java
佛祖让我来巡山2 小时前
深入理解JVM内存分配机制:大对象处理、年龄判定与空间担保
jvm·内存分配·大对象处理·空间担保·年龄判定
渣哥2 小时前
原来 Java 里线程安全集合有这么多种
java
间彧3 小时前
Spring Boot集成Spring Security完整指南
java
间彧3 小时前
Spring Secutiy基本原理及工作流程
java
数据智能老司机4 小时前
精通 Python 设计模式——创建型设计模式
python·设计模式·架构
Java水解4 小时前
JAVA经典面试题附答案(持续更新版)
java·后端·面试
数据智能老司机5 小时前
精通 Python 设计模式——SOLID 原则
python·设计模式·架构
洛小豆6 小时前
在Java中,Integer.parseInt和Integer.valueOf有什么区别
java·后端·面试
前端小张同学7 小时前
服务器上如何搭建jenkins 服务CI/CD😎😎
java·后端