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

发布于:2025-07-14 ⋅ 阅读:(19) ⋅ 点赞:(0)

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

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

在软件开发中,对象创建是最常见的操作之一。当代码中充满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 代码实现

// 产品接口
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 代码实现

// 抽象工厂
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案例

// 抽象产品族
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中的工厂模式

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

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

5.2 Spring框架的工厂应用

// 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的日志工厂

Logger logger = LogManager.getLogger(); // 获取日志器工厂

六、工厂模式最佳实践

6.1 何时使用工厂模式?

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

6.2 设计原则落地

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

6.3 避免常见误区

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

七、工厂模式演进与变种

7.1 静态工厂方法

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

7.2 参数化工厂

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

7.3 延迟初始化工厂

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)

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


网站公告

今日签到

点亮在社区的每一天
去签到