一、前言:为什么需要创建型模式?
在软件开发过程中,对象的创建可能是最频繁的操作。假设你要开汉堡店,选择原料供应商(如何造汉堡)、定制套餐组合(如何组织对象)、应对突发需求(如何适应变化)都需要策略。这时设计模式就像经营手册,下面我们聚焦三个最常见的创建模式。
二、工厂方法模式:单品生产线
2.1 模式定义
工厂方法定义一个接口用于创建对象,但让子类决定实例化哪个类。如同特许经营店,总部制定标准,分店自行选择配料。
// 技术栈:Java 17
interface Burger {
void addSauce();
}
class BeefBurger implements Burger {
@Override
public void addSauce() {
System.out.println("添加黑椒酱汁");
}
}
abstract class BurgerShop {
// 工厂方法声明
public abstract Burger createBurger();
public void orderBurger() {
Burger burger = createBurger();
burger.addSauce();
}
}
class BeefBurgerShop extends BurgerShop {
@Override
public Burger createBurger() {
return new BeefBurger();
}
}
// 使用示例
public class Main {
public static void main(String[] args) {
BurgerShop shop = new BeefBurgerShop();
shop.orderBurger(); // 输出:添加黑椒酱汁
}
}
2.2 应用场景
- 快递系统需要区分不同运输方式
- 游戏装备需要根据角色职业生成不同武器
- 日志系统需要支持多种日志记录方式
三、抽象工厂模式:全套供应链
3.1 双重抽象设计
当需要生产整套相关产品时,抽象工厂就像连锁餐厅的中央厨房:
// 完整套餐接口
interface MealCombo {
Burger createBurger();
Drink createDrink();
}
// 美式风味工厂
class AmericanCombo implements MealCombo {
@Override
public Burger createBurger() {
return new BeefBurger();
}
@Override
public Drink createDrink() {
return new Cola();
}
}
// 中式风味工厂
class ChineseCombo implements MealCombo {
@Override
public Burger createBurger() {
return new PorkBurger();
}
@Override
public Drink createDrink() {
return new SoyMilk();
}
}
// 使用示例
public class Kitchen {
public void prepareMeal(MealCombo factory) {
Burger burger = factory.createBurger();
Drink drink = factory.createDrink();
// 打包操作...
}
}
3.2 核心技术特征
- 产品之间强关联性(如操作系统主题组件)
- 需要约束产品兼容性(如汽车不同型号的配件)
- 整体替换产品族更方便
四、建造者模式:分步装配大师
4.1 灵活构建流程
面对复杂对象,建造者模式像乐高说明书:
class CustomBurger {
private List<String> layers = new ArrayList<>();
public void addLayer(String ingredient) {
layers.add(ingredient);
}
public void showBurger() {
System.out.println("当前汉堡结构:" + String.join("+", layers));
}
}
// 建造者接口
interface BurgerBuilder {
void addBread();
void addPatty();
void addVegetables();
CustomBurger getResult();
}
class DeluxeBuilder implements BurgerBuilder {
private CustomBurger burger = new CustomBurger();
@Override
public void addBread() {
burger.addLayer("全麦面包");
}
@Override
public void addPatty() {
burger.addLayer("双层牛肉饼");
}
@Override
public void addVegetables() {
burger.addLayer("生菜+番茄");
}
@Override
public CustomBurger getResult() {
return burger;
}
}
// 导演类控制流程
class Chef {
public CustomBurger construct(BurgerBuilder builder) {
builder.addBread();
builder.addPatty();
builder.addVegetables();
builder.addBread();
return builder.getResult();
}
}
4.2 模式优势验证
- 允许通过不同Builder实现改变内部结构
- 避免构造函数参数爆炸(特别是可选参数多的场景)
- 支持渐进式对象构建
五、模式对比与选型指南
5.1 适用场景对照表
| 模式名称 | 最佳使用场景 | 典型案例 |
|---|---|---|
| 工厂方法 | 单个产品的多态创建 | 数据库连接器选择 |
| 抽象工厂 | 相关产品族的创建 | 跨平台UI组件套件 |
| 建造者 | 复杂对象的分步构造 | HTTP请求配置器 |
5.2 技术选型注意事项
- 避免过度设计:简单对象直接使用new关键字
- 关注扩展方向:垂直扩展选工厂,水平组合用建造者
- 考虑组合使用:抽象工厂中可以使用工厂方法创建单个产品
六、生产环境中的实战经验
6.1 Spring框架中的典型应用
- @Bean注解本质是工厂方法
- BeanFactory与ApplicationContext的关系体现抽象工厂层级
- RestTemplateBuilder是建造者模式的优秀实践
6.2 性能优化要点
- 工厂类可以配合缓存机制提升性能
- 建造者模式较适合创建重量级对象
- 抽象工厂要注意避免创建不必要的子类
七、总结:模式之外的设计哲学
- 隔离变化:将可能变化的创建逻辑与业务逻辑解耦
- 提升内聚:每个类保持单一职责
- 开放封闭:通过新增实现类扩展功能,而不是修改原有代码
评论