程序员老张每次经过奶茶店都特别有感触:不同的店员使用标准操作流程制作饮品,其实和软件开发中的工厂模式有异曲同工之妙。今天我们就用现实生活中熟悉的例子,搭配代码实例,把看似高深的工厂模式掰开揉碎讲明白。
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. 技术选型决策树
![技术选型流程图(文字描述版)] 当面临模式选择时,可参考:
- 产品是否单一? → 简单工厂
- 需要灵活扩展? → 工厂方法
- 涉及多个关联产品? → 抽象工厂
- 都符合?优先选择简单方案
5. 常见坑点指南
- 过度设计警告:小型项目使用简单工厂即可时,不要强行用抽象工厂
- 版本兼容问题:工厂模式创建的实例需要确保接口稳定性
- 测试注意事项:使用工厂模式后,单元测试需要mock整个工厂
6. 总结与实践建议
经过三个版本的迭代演进,我们总结出:
- 简单工厂就像标准化流水线,适合快速产出
- 工厂方法如同特许经营,保持核心规范同时允许个性化
- 抽象工厂则像米其林套餐,强调产品间的完美搭配
在真实项目开发中,建议先用简单工厂实现MVP,当确实出现扩展需求时再重构升级。就像星巴克最初也只是个咖啡小馆,发展壮大后才需要建立完整的供应链体系。
评论