程序员老张每次经过奶茶店都特别有感触:不同的店员使用标准操作流程制作饮品,其实和软件开发中的工厂模式有异曲同工之妙。今天我们就用现实生活中熟悉的例子,搭配代码实例,把看似高深的工厂模式掰开揉碎讲明白。

1. 简单工厂模式:奶茶店的中央厨房

1.1 场景复现

想象一个奶茶中央厨房:收到订单时不需要知道具体配方,只要告诉机器"珍珠奶茶",就能得到标准产品。这正是简单工厂模式的精髓。

技术栈:Java 11

// 抽象产品
interface MilkTea {
    void prepare();
}

// 具体产品
class PearlMilkTea implements MilkTea {
    @Override
    public void prepare() {
        System.out.println("泡红茶+加珍珠+加奶盖");
    }
}

class MangoSago implements MilkTea {
    @Override
    public void prepare() {
        System.out.println("芒果切块+西米露+椰奶");
    }
}

// 简单工厂
class SimpleTeaFactory {
    public MilkTea createTea(String type) {
        switch (type.toLowerCase()) {
            case "pearl":
                return new PearlMilkTea();
            case "mango":
                return new MangoSago();
            default:
                throw new IllegalArgumentException("未知奶茶类型");
        }
    }
}

// 使用示例
public class Client {
    public static void main(String[] args) {
        SimpleTeaFactory factory = new SimpleTeaFactory();
        MilkTea tea = factory.createTea("pearl");
        tea.prepare();  // 输出:泡红茶+加珍珠+加奶盖
    }
}

1.2 应用特点

  • 适用场景:标准产品、产品种类有限、创建逻辑简单
  • 优点:减少客户端与具体类耦合,实现创建逻辑复用
  • 缺点:新增产品必须修改工厂类,违反开闭原则

1.3 特别说明

在Spring框架中,BeanFactory可以看作是加强版的简单工厂实现。我们通过XML配置或注解声明Bean,框架自动完成实例化,这种机制极大简化了对象的创建过程。

2. 工厂方法模式:连锁汉堡店的秘籍

2.1 需求演进

当奶茶店升级为全国连锁时,各地区的珍珠奶茶需要差异化(上海偏甜、成都加辣)。此时适合采用工厂方法模式——每个分店继承统一的制作规范,但实现自己的特色版本。

技术栈:Java 11

// 抽象工厂
interface BurgerFactory {
    Burger createBurger();
}

// 上海分店
class ShanghaiBurgerFactory implements BurgerFactory {
    @Override
    public Burger createBurger() {
        return new Burger("特制甜面酱", "加厚肉饼");
    }
}

// 成都分店
class ChengduBurgerFactory implements BurgerFactory {
    @Override
    public Burger createBurger() {
        return new Burger("麻辣酱料", "酥脆炸鸡");
    }
}

// 产品类
class Burger {
    private String sauce;
    private String patty;

    public Burger(String sauce, String patty) {
        this.sauce = sauce;
        this.patty = patty;
        System.out.println("制作汉堡:" + patty + "配" + sauce);
    }
}

// 客户端调用
public class Client {
    public static void main(String[] args) {
        BurgerFactory shFactory = new ShanghaiBurgerFactory();
        shFactory.createBurger();  // 输出:制作汉堡:加厚肉饼配特制甜面酱

        BurgerFactory cdFactory = new ChengduBurgerFactory();
        cdFactory.createBurger();  // 输出:制作汉堡:酥脆炸鸡配麻辣酱料
    }
}

2.2 进阶实践

工厂方法在Java标准库中有典型应用,比如:

// JDBC中的DriverManager
Connection conn = DriverManager.getConnection(url);
// 日志框架中的LoggerFactory
Logger logger = LoggerFactory.getLogger(MyClass.class);

2.3 模式对比

维度 简单工厂 工厂方法
扩展性 修改原类 新增子类
复杂度
适用场景 固定类型产品 系列化产品家族

3. 抽象工厂模式:豪华套餐的诞生

3.1 复杂需求

当需要组合多种相关产品(如汉堡+薯条+饮料的套餐),抽象工厂就派上用场了。它能确保产品之间的兼容性——你不会想要麦辣鸡腿堡配星巴克的咖啡杯。

技术栈:Java 11

// 抽象工厂
interface ComboFactory {
    Burger createBurger();
    Drink createDrink();
}

// 夏日限定套餐
class SummerComboFactory implements ComboFactory {
    @Override
    public Burger createBurger() {
        return new Burger("菠萝酱", "烤鸡腿");
    }

    @Override
    public Drink createDrink() {
        return new Drink("冰镇柠檬茶");
    }
}

// 冬日温暖套餐
class WinterComboFactory implements ComboFactory {
    @Override
    public Burger createBurger() {
        return new Burger("黑椒酱", "厚切牛排");
    }

    @Override
    public Drink createDrink() {
        return new Drink("热巧克力");
    }
}

// 客户端
public class Client {
    public static void main(String[] args) {
        ComboFactory factory = new SummerComboFactory();
        factory.createBurger();  // 烤鸡腿配菠萝酱
        factory.createDrink();   // 冰镇柠檬茶
    }
}

3.2 真实案例

Spring框架中的FactoryBean接口是抽象工厂的典型实现。开发者可以通过实现这个接口,创建复杂对象的工厂,例如整合第三方库的适配器。

4. 技术选型决策树

![技术选型流程图(文字描述版)] 当面临模式选择时,可参考:

  1. 产品是否单一? → 简单工厂
  2. 需要灵活扩展? → 工厂方法
  3. 涉及多个关联产品? → 抽象工厂
  4. 都符合?优先选择简单方案

5. 常见坑点指南

  1. 过度设计警告:小型项目使用简单工厂即可时,不要强行用抽象工厂
  2. 版本兼容问题:工厂模式创建的实例需要确保接口稳定性
  3. 测试注意事项:使用工厂模式后,单元测试需要mock整个工厂

6. 总结与实践建议

经过三个版本的迭代演进,我们总结出:

  • 简单工厂就像标准化流水线,适合快速产出
  • 工厂方法如同特许经营,保持核心规范同时允许个性化
  • 抽象工厂则像米其林套餐,强调产品间的完美搭配

在真实项目开发中,建议先用简单工厂实现MVP,当确实出现扩展需求时再重构升级。就像星巴克最初也只是个咖啡小馆,发展壮大后才需要建立完整的供应链体系。