一、走进创建型模式的时空隧道

凌晨三点的IDE依然亮着,王工盯着满屏重复的new操作突然意识到——自己正在重复造轮子。开发游戏引擎时,不同类型的角色创建逻辑相互纠缠;编写支付系统时,商户接入逻辑像野草般疯长。这种似曾相识的困境,正是创建型设计模式要解决的核心问题。

创建型模式如同程序员手中的魔法棒,它们既能把复杂的构建逻辑封装在精美的框架里,也能让对象创建的过程充满弹性。今天我们将通过三个典型案例,用Java语言一探工厂方法、抽象工厂和建造者模式的实战奥秘。

二、工厂方法:灵活生产的万能车间

2.1 快餐店的订单革命

想象一个汉堡连锁店,不同分店需要制作特色汉堡。传统方式是这样的:

// 传统方式的分店实现
public class BurgerStore {
    public Burger orderBurger(String type) {
        Burger burger;
        if ("classic".equals(type)) {
            burger = new ClassicBurger();
        } else if ("spicy".equals(type)) {
            burger = new SpicyBurger();
        } else {
            throw new IllegalArgumentException("未知类型");
        }
        burger.prepare();
        burger.cook();
        return burger;
    }
}

这种硬编码方式在新增产品时就像改造厂房——需要停产整修,而工厂方法给出了创新方案:

// 工厂方法抽象
public abstract class BurgerStore {
    public Burger orderBurger(String type) {
        Burger burger = createBurger(type);
        burger.prepare();
        burger.cook();
        return burger;
    }

    // 核心的工厂方法
    protected abstract Burger createBurger(String type);
}

// 上海分店实现
public class ShanghaiStore extends BurgerStore {
    @Override
    protected Burger createBurger(String type) {
        switch (type) {
            case "classic": return new ShangHaiClassicBurger();
            case "crab": return new CrabBurger(); // 新增特色产品
            default: throw new IllegalArgumentException();
        }
    }
}

2.2 工厂方法的双重优势

  1. 扩展自由:新增分店只需继承抽象类,不影响既有代码
  2. 责任清晰:各分店专注产品实现,总部负责制作流程

但在实际开发中要注意:

  • 工厂类层次可能随产品种类快速膨胀
  • 简单的参数工厂可能不如直接new直观(适用于复杂场景)

三、抽象工厂:构建产品家族的帝国

3.1 电脑城的重生计划

当我们需要生产互相配合的硬件组件时,抽象工厂成为利器。传统组装方式可能存在兼容风险:

// 混乱的组装方式
public class Computer {
    public Computer(String brand) {
        if ("dell".equals(brand)) {
            cpu = new DellCPU();
            motherboard = new AsusMotherboard(); // 混合品牌风险
        }
    }
}

引入抽象工厂后:

// 硬件工厂接口
public interface HardwareFactory {
    CPU createCPU();
    Motherboard createMotherboard();
}

// 戴尔实现
public class DellFactory implements HardwareFactory {
    @Override
    public CPU createCPU() { 
        return new DellCorei9(); 
    }

    @Override
    public Motherboard createMotherboard() {
        return new DellAlienwareBoard();
    }
}

// 组装车间
public class ComputerAssembler {
    private HardwareFactory factory;

    public ComputerAssembler(HardwareFactory factory) {
        this.factory = factory;
    }

    public Computer build() {
        Computer computer = new Computer();
        computer.installCPU(factory.createCPU());
        computer.installMotherboard(factory.createMotherboard());
        return computer;
    }
}

3.2 工厂金字塔的启示

  • 跨平台UI开发:Android/iOS组件工厂保持界面风格统一
  • 数据库适配:不同数据库厂商的驱动封装
  • 游戏引擎:不同渲染管线的材质系统

但要注意避免的陷阱:

  • 新增产品类型需要修改所有工厂实现(违反开闭原则)
  • 简单场景可能带来不必要的复杂度

四、建造者模式:精雕细琢的艺术品创作

4.1 角色创建的涅槃之路

当我们面对包含数十个参数的游戏角色创建时,传统构造方式会让代码可读性崩溃:

// 参数爆炸的构造器
Character warrior = new Character("战士", 100, 50, 30, 
    Equipment.SWORD, Armor.PLATE, ...);

建造者模式给出了优雅解决方案:

public class Character {
    private String name;
    private int strength;
    private int agility;
    private Equipment weapon;
    // ...20+属性

    private Character(Builder builder) {
        this.name = builder.name;
        this.strength = builder.strength;
        this.agility = builder.agility;
        this.weapon = builder.weapon;
    }

    public static class Builder {
        private String name;
        private int strength;
        private int agility;
        private Equipment weapon = Equipment.FIST;

        public Builder(String name) {
            this.name = name;
        }

        public Builder strength(int val) {
            strength = val;
            return this;
        }

        public Builder agility(int val) {
            agility = val;
            return this;
        }

        public Builder weapon(Equipment weapon) {
            this.weapon = weapon;
            return this;
        }

        public Character build() {
            validate();
            return new Character(this);
        }

        private void validate() {
            if (strength + agility > 150) {
                throw new IllegalStateException("属性总和超标");
            }
        }
    }
}

// 客户端使用
Character paladin = new Character.Builder("圣骑士")
    .strength(80)
    .agility(30)
    .weapon(Equipment.HOLY_SWORD)
    .build();

4.2 建造者的独到之处

  • 分步构建:支持复杂对象的逐步创建
  • 参数验证:可在build()方法中进行统一校验
  • 不可变对象:确保构建后的对象安全性

但在实际应用中需要注意:

  • 建造者类的维护成本
  • 较简单的对象可能"杀鸡用牛刀"

五、模式选择的黄金法则

5.1 应用场景全景

模式名称 最佳适用场景 典型案例
工厂方法 存在多个平行产品线 跨平台的UI组件生成
抽象工厂 需要组合相关产品家族 数据库连接工厂(连接+语句+结果集)
建造者 复杂对象的逐步构建 HTTP请求配置、报表生成器

5.2 技术特性深度对比

扩展维度比较

  • 工厂方法扩展产品种类(纵向扩展)
  • 抽象工厂扩展产品家族(横向扩展)
  • 建造者扩展构建过程(深度扩展)

性能考虑

  • 简单工厂的内存开销更小
  • 抽象工厂需要权衡类爆炸问题
  • 建造者模式适合构建重型对象

六、实战中的模式演进

6.1 Spring中的工厂魔法

Spring框架将工厂方法提升到新高度,通过@Bean注解实现:

@Configuration
public class PaymentConfig {
    @Bean
    @Scope("prototype")
    public PaymentService alipayService() {
        return new AlipayServiceV2(config);
    }
    
    @Bean
    public PaymentProcessor paymentProcessor() {
        return new PaymentProcessor(alipayService());
    }
}

IoC容器本身就是抽象工厂的高级实现,管理着各种Bean的创建与依赖。

6.2 Lombok的建造者实践

通过注解自动生成建造者:

@Builder
@Accessors(chain = true)
public class Order {
    private String orderId;
    private BigDecimal amount;
    private PaymentType paymentType;
}

// 链式构建
Order order = Order.builder()
    .orderId("20230415001")
    .amount(new BigDecimal("199.99"))
    .paymentType(PaymentType.WECHAT)
    .build();

七、创造的艺术

在对象创建的十字路口,每个模式都闪耀着智慧的光芒。工厂方法是灵活的分身术,抽象工厂是精妙的组合技,建造者则是耐心的雕塑家。但真正的技术高手懂得:

  1. 避免为了模式而模式——简单胜于复杂
  2. 灵活组合多种模式——如工厂方法+建造者
  3. 关注模式演进——如Spring等框架的升级

最终的代码艺术,是能在模式之美与实现简洁之间找到完美的平衡点。当您下次面对new关键字时,不妨停顿三秒思考:是否有更优雅的创造方式?