通俗且全面精讲工厂设计模式

文章目录

前言:为什么你需要学习工厂模式?

想象一下,如果你每次想吃披萨都要自己种小麦、养奶牛、建烤炉...这太疯狂了!在编程世界中,工厂模式就是帮我们避免这种"重复造轮子"的智慧。

学完本教程,你将:

  • 真正理解工厂模式的核心思想
  • 掌握三种工厂模式的应用场景
  • 能在实际项目中正确使用工厂模式
  • 写出更优雅、更易维护的代码

第一章:工厂模式是什么?用生活化例子理解

1.1 核心概念:专业的人做专业的事

工厂模式的本质: 把对象的创建过程"外包"给专门的工厂类,让使用者不需要关心对象是怎么被创建出来的。

1.2 现实生活中的工厂模式

场景1:点外卖 🍔

  • 不用工厂模式:你要记住每个餐厅的电话、菜单、价格
  • 用工厂模式:打开外卖APP → 选择品类 → 下单 → 等送达

场景2:买汽车 🚗

  • 不用工厂模式:你自己造发动机、装轮胎、喷漆
  • 用工厂模式:去4S店说"我要SUV" → 付钱 → 开走

场景3:装修房子 🏠

  • 不用工厂模式:你自己买建材、找木工、找电工
  • 用工厂模式:找装修公司 → 说明风格需求 → 等完工验收

第二章:三种工厂模式详解

2.1 简单工厂模式:像自动售货机

什么是简单工厂?

最简单的工厂形式,一个工厂类负责创建所有类型的对象。

代码示例:饮料售货机
java 复制代码
// 产品接口
interface Drink {
    void drink();
}

// 具体产品
class Cola implements Drink {
    public void drink() {
        System.out.println("喝可乐");
    }
}

class Sprite implements Drink {
    public void drink() {
        System.out.println("喝雪碧");
    }
}

// 简单工厂(售货机)
class DrinkFactory {
    public Drink getDrink(String type) {
        if ("cola".equals(type)) {
            return new Cola();
        } else if ("sprite".equals(type)) {
            return new Sprite();
        }
        throw new IllegalArgumentException("未知饮料类型");
    }
}

// 使用
public class Main {
    public static void main(String[] args) {
        DrinkFactory factory = new DrinkFactory();
        
        // 顾客只需要知道要什么饮料,不用关心怎么生产的
        Drink cola = factory.getDrink("cola");
        cola.drink();  // 输出:喝可乐
        
        Drink sprite = factory.getDrink("sprite");
        sprite.drink(); // 输出:喝雪碧
    }
}
适用场景:
  • 产品类型较少且固定
  • 不需要频繁添加新产品
  • 适合小型项目或学习入门
优缺点:
  • ✅ 优点:简单易用,代码直观
  • ❌ 缺点:添加新产品需要修改工厂类,违反开闭原则

2.2 工厂方法模式:像专业餐厅联盟

什么是工厂方法?

定义一个创建对象的接口,但让子类决定实例化哪个类。工厂方法让类的实例化延迟到子类。

代码示例:餐厅系统
java 复制代码
// 产品:食物
interface Food {
    void cook();
}

class Pizza implements Food {
    public void cook() {
        System.out.println("烤制披萨");
    }
}

class Sushi implements Food {
    public void cook() {
        System.out.println("制作寿司");
    }
}

// 抽象工厂:餐厅
abstract class Restaurant {
    // 点餐流程是固定的
    public Food orderFood() {
        Food food = createFood();  // 让具体餐厅决定做什么
        food.cook();
        System.out.println("食物准备好了!");
        return food;
    }
    
    // 工厂方法:每个餐厅自己实现
    protected abstract Food createFood();
}

// 具体工厂:披萨店
class PizzaRestaurant extends Restaurant {
    protected Food createFood() {
        return new Pizza();
    }
}

// 具体工厂:寿司店
class SushiRestaurant extends Restaurant {
    protected Food createFood() {
        return new Sushi();
    }
}

// 使用
public class Main {
    public static void main(String[] args) {
        // 想去披萨店
        Restaurant pizzaShop = new PizzaRestaurant();
        Food pizza = pizzaShop.orderFood();
        // 输出:烤制披萨 → 食物准备好了!
        
        // 想去寿司店
        Restaurant sushiShop = new SushiRestaurant();
        Food sushi = sushiShop.orderFood();
        // 输出:制作寿司 → 食物准备好了!
    }
}
适用场景:
  • 产品类型可能会不断增加
  • 需要更灵活的创建逻辑
  • 不同产品有不同的创建过程
优缺点:
  • ✅ 优点:符合开闭原则,扩展性好
  • ❌ 缺点:类的数量会增加,复杂度稍高

2.3 抽象工厂模式:像整体装修公司

什么是抽象工厂?

创建相关或依赖对象的家族,而不需要明确指定具体类。

代码示例:UI主题系统
java 复制代码
// 产品族:按钮
interface Button {
    void render();
}

class WindowsButton implements Button {
    public void render() {
        System.out.println("渲染Windows风格按钮");
    }
}

class MacButton implements Button {
    public void render() {
        System.out.println("渲染Mac风格按钮");
    }
}

// 产品族:文本框
interface TextBox {
    void display();
}

class WindowsTextBox implements TextBox {
    public void display() {
        System.out.println("显示Windows风格文本框");
    }
}

class MacTextBox implements TextBox {
    public void display() {
        System.out.println("显示Mac风格文本框");
    }
}

// 抽象工厂接口
interface GUIFactory {
    Button createButton();
    TextBox createTextBox();
}

// 具体工厂:Windows风格
class WindowsFactory implements GUIFactory {
    public Button createButton() {
        return new WindowsButton();
    }
    
    public TextBox createTextBox() {
        return new WindowsTextBox();
    }
}

// 具体工厂:Mac风格
class MacFactory implements GUIFactory {
    public Button createButton() {
        return new MacButton();
    }
    
    public TextBox createTextBox() {
        return new MacTextBox();
    }
}

// 使用
public class Application {
    private Button button;
    private TextBox textBox;
    
    public Application(GUIFactory factory) {
        button = factory.createButton();
        textBox = factory.createTextBox();
    }
    
    public void render() {
        button.render();
        textBox.display();
    }
}

// 主程序
public class Main {
    public static void main(String[] args) {
        // 创建Windows风格的应用
        GUIFactory windowsFactory = new WindowsFactory();
        Application windowsApp = new Application(windowsFactory);
        windowsApp.render();
        // 输出:渲染Windows风格按钮 → 显示Windows风格文本框
        
        // 创建Mac风格的应用
        GUIFactory macFactory = new MacFactory();
        Application macApp = new Application(macFactory);
        macApp.render();
        // 输出:渲染Mac风格按钮 → 显示Mac风格文本框
    }
}
适用场景:
  • 需要创建相关产品家族
  • 要保证产品之间的兼容性
  • 系统需要切换不同的产品系列
优缺点:
  • ✅ 优点:产品兼容性好,切换产品族容易
  • ❌ 缺点:扩展新产品族比较困难

第三章:实际项目中的应用场景

3.1 数据库连接池

java 复制代码
// 不用工厂模式
if (dbType.equals("MySQL")) {
    connection = new MySQLConnection();
} else if (dbType.equals("Oracle")) {
    connection = new OracleConnection();
}

// 使用工厂模式
connection = ConnectionFactory.createConnection(dbType);

3.2 日志系统

java 复制代码
// 工厂帮你决定日志输出方式
Logger logger = LoggerFactory.getLogger(config.getLogType());
logger.info("用户登录成功");

3.3 支付网关

java 复制代码
// 根据配置选择支付方式
Payment payment = PaymentFactory.createPayment(order.getPaymentMethod());
payment.process(amount);

3.4 游戏开发

java 复制代码
// 根据关卡生成不同敌人
Enemy enemy = EnemyFactory.spawnEnemy(currentLevel);
enemy.attack();

第四章:如何选择正确的工厂模式?

决策流程图:

复制代码
开始选择工厂模式
    ↓
需要创建单个产品还是产品家族?
    ↓
单个产品 → 产品类型是否固定?
    ↓
固定 → 简单工厂模式(简单直接)
不固定 → 工厂方法模式(易于扩展)
    ↓
产品家族 → 抽象工厂模式(保证兼容性)

选择指南:

场景 推荐模式 理由
小型工具类 简单工厂 简单够用
插件系统 工厂方法 易于扩展新插件
跨平台UI 抽象工厂 保证界面风格一致
数据访问层 工厂方法 支持多种数据库
游戏物品系统 抽象工厂 装备套装效果

第五章:最佳实践和常见陷阱

5.1 最佳实践 ✅

  1. 遵循单一职责原则

    • 工厂类只负责创建对象
    • 业务逻辑放在产品类中
  2. 使用接口编程

    • 针对接口编程,而不是实现
    • 提高代码的灵活性
  3. 合理使用配置

    • 通过配置文件决定创建哪种产品
    • 避免硬编码

5.2 常见陷阱 ❌

  1. 过度设计

    java 复制代码
    // 不要这样:简单对象也用复杂工厂
    String str = StringFactory.createString("hello");
    
    // 应该这样:直接创建
    String str = "hello";
  2. 工厂类过于庞大

    • 如果一个工厂类有太多if-else,考虑拆分成多个工厂
  3. 忽略异常处理

    java 复制代码
    // 不好的做法
    public Product createProduct(String type) {
        if ("A".equals(type)) return new ProductA();
        return null;  // 可能返回null
    }
    
    // 好的做法
    public Product createProduct(String type) {
        if ("A".equals(type)) return new ProductA();
        throw new IllegalArgumentException("不支持的产品类型: " + type);
    }

第六章:实战练习

练习1:简单的通知系统

创建一个通知工厂,支持邮件通知、短信通知、推送通知。

练习2:跨平台文件对话框

使用抽象工厂模式创建Windows和Mac风格的打开/保存文件对话框。

练习3:游戏武器系统

实现一个武器工厂,能够创建不同稀有度(普通、稀有、史诗)的武器。


总结

工厂模式的核心价值在于解耦封装。通过本教程的学习,你应该能够:

  1. 理解三种工厂模式的区别和应用场景
  2. 在实际项目中正确选择和使用工厂模式
  3. 写出更清晰、更易维护的代码

记住:不要重复造轮子,让专业的工厂来帮你创建对象!

如果有任何问题,欢迎随时提问!Happy Coding! 🚀

相关推荐
进击的小头2 小时前
设计模式与C语言高级特性的结合
c语言·设计模式
小温冲冲2 小时前
通俗且全面精讲单例设计模式
开发语言·javascript·设计模式
Vivienne_ChenW2 小时前
DDD领域模型在项目中的实战
java·开发语言·后端·设计模式
sg_knight3 小时前
原型模式(Prototype)
python·设计模式·开发·原型模式
短剑重铸之日4 小时前
《设计模式》第九篇:三大类型之结构型模式
java·后端·设计模式·组合模式·代理模式·结构性模式
忧郁的Mr.Li4 小时前
设计模式--单例模式
javascript·单例模式·设计模式
范纹杉想快点毕业5 小时前
状态机设计模式与嵌入式系统开发完整指南
java·开发语言·网络·数据库·mongodb·设计模式·架构
短剑重铸之日5 小时前
《设计模式》第十篇:三大类型之行为型模式
java·后端·设计模式·责任链模式·访问者模式·行为型模式
YigAin5 小时前
Unity23种设计模式之 解释器模式
设计模式·解释器模式