网站Logo Ilren 小记

Java设计模式-工厂模式

jack
25
2023-05-03

工厂模式(Factory Pattern):掌控对象创建的艺术

模式简介
工厂模式是一种创建型设计模式,它定义了一个创建对象的接口,但将具体实例化的工作推迟到子类。
就像现实中的工厂生产产品一样,它把new操作封装起来,让代码更加灵活可扩展。


📦 应用场景

  • 需要创建多种相似对象(如不同数据库连接)
  • 对象创建过程复杂(需要多步初始化)
  • 需要统一管理对象生命周期
  • 希望隐藏具体实现类(如JDBC驱动加载)
  • Spring框架的BeanFactory
  • 日志框架的LoggerFactory

🧠 核心实现思路

  1. 定义产品接口(抽象产品)
  2. 创建具体产品类
  3. 定义工厂接口(抽象工厂)
  4. 实现具体工厂类
  5. 客户端通过工厂获取对象,而非直接new

🧱 工厂模式的多种实现方式

1. 简单工厂(静态工厂)

public class PizzaFactory {
    public static Pizza createPizza(String type) {
        switch (type) {
            case "cheese": return new CheesePizza();
            case "pepperoni": return new PepperoniPizza();
            default: throw new IllegalArgumentException("Unknown pizza type");
        }
    }
}

优点:实现简单
缺点:违反开闭原则,新增类型需修改工厂

2. 工厂方法模式(推荐)

public interface PizzaFactory {
    Pizza createPizza();
}

public class NYPizzaFactory implements PizzaFactory {
    @Override
    public Pizza createPizza() {
        return new NYStyleCheesePizza();
    }
}

优点:符合开闭原则,扩展性强
缺点:类数量增加

3. 抽象工厂模式(产品族)

public interface GUIFactory {
    Button createButton();
    Checkbox createCheckbox();
}

public class WinFactory implements GUIFactory {
    @Override
    public Button createButton() {
        return new WinButton();
    }
    // 其他产品创建方法...
}

优点:能创建相关对象族
缺点:系统复杂度高

💎 最佳实现推荐

静态工厂 + 注册表(Spring风格)

public class BeanFactory {
    private static final Map<String, Supplier<Object>> registry = new HashMap<>();
    
    static {
        registry.put("userService", UserService::new);
        registry.put("orderService", OrderService::new);
    }
    
    public static Object getBean(String name) {
        return registry.get(name).get();
    }
}

枚举工厂(线程安全)

public enum LoggerFactory {
    FILE {
        public Logger create() { return new FileLogger(); }
    },
    CONSOLE {
        public Logger create() { return new ConsoleLogger(); }
    };
    
    public abstract Logger create();
}

💣 常见问题与解决方案

问题1:如何避免工厂类膨胀?

解决方案
使用Map维护创建逻辑,如Spring的BeanDefinitionRegistry

问题2:如何支持动态扩展?

解决方案
结合SPI机制(ServiceLoader)或反射

问题3:循环依赖如何处理?

解决方案

  • 使用三级缓存(参考Spring)

  • 改为Setter注入

📊 模式对比

模式类型 灵活性
(1-3★)
复杂度
(1-3★)
适用场景
简单工厂 ⭐⭐☆ ⭐☆☆ 固定类型少量变化
工厂方法 ⭐⭐⭐ ⭐⭐☆ 需要扩展的子类体系
抽象工厂 ⭐⭐⭐ ⭐⭐⭐ 相关产品族创建

📚 实际应用案例

  1. JDBC中的工厂模式
Connection conn = DriverManager.getConnection(url);
// DriverManager就是连接工厂
  1. Spring框架
@Bean
public DataSource dataSource() {
    return new HikariDataSource(); // 数据源工厂
}
  1. Java集合框架
List<String> list = Collections.unmodifiableList(originalList);
// Collections是集合装饰器的工厂

🎯 总结建议

  1. 优先选择:工厂方法模式(符合开闭原则)

  2. 性能考量:对高频创建对象使用对象池

  3. 框架整合:Spring中优先使用@Bean注解

  4. 避免滥用:简单对象直接new更清晰

  5. 设计原则:依赖抽象(工厂接口),而非具体实现

动物装饰