Java工厂模式案例

wen java案例 2

本文目录导读:

Java工厂模式案例

  1. 目录导读
  2. 工厂模式为什么重要?
  3. 简单工厂模式 —— 最直观的“制造车间”案例
  4. 工厂方法模式 —— 让子类决定实例化哪个类(支付场景实战)
  5. 抽象工厂模式 —— 打造“产品族”的终极方案(跨平台UI案例)
  6. 三大工厂模式对比与选型决策表
  7. 高频面试问答与常见坑
  8. 如何在实际项目中优雅落地工厂模式

目录导读

  1. 工厂模式为什么重要?—— 解耦与扩展的基石
  2. 简单工厂模式 —— 最直观的“制造车间”案例(含代码)
  3. 工厂方法模式 —— 让子类决定实例化哪个类(支付场景实战)
  4. 抽象工厂模式 —— 打造“产品族”的终极方案(跨平台UI案例)
  5. 三大工厂模式对比与选型决策表
  6. 高频面试问答与常见坑(含设计原则分析)
  7. 如何在实际项目中优雅落地工厂模式

工厂模式为什么重要?

在Java开发中,new关键字是最直接的创建对象方式,但硬编码具体类会导致模块间的紧耦合,工厂模式的核心价值在于:将对象的创建逻辑封装起来,使客户端代码依赖于抽象接口而非具体实现,这符合“开闭原则”和“依赖倒置原则”。

根据Oracle官方文档及Gof《设计模式》的描述,工厂模式分为三种形态:简单工厂(非23种)、工厂方法、抽象工厂。在实际Spring框架中,BeanFactory就是工厂模式的经典应用,它通过配置文件控制对象创建,实现控制反转。


简单工厂模式 —— 最直观的“制造车间”案例

场景:开发一个日志记录器,支持控制台输出和文件输出两种方式。

// 抽象产品
public interface Logger { void log(String message); }
// 具体产品A
public class ConsoleLogger implements Logger {
    public void log(String message) { System.out.println("Console: " + message); }
}
// 具体产品B
public class FileLogger implements Logger {
    public void log(String message) { System.out.println("File: " + message); }
}
// 简单工厂(Static Factory)
public class LoggerFactory {
    public static Logger createLogger(String type) {
        if ("console".equalsIgnoreCase(type)) return new ConsoleLogger();
        else if ("file".equalsIgnoreCase(type)) return new FileLogger();
        throw new IllegalArgumentException("Unknown logger type");
    }
}
// 客户端
public class Client {
    public static void main(String[] args) {
        Logger logger = LoggerFactory.createLogger("file");
        logger.log("订单创建成功");
    }
}

分析:简单工厂将创建逻辑集中在一个类中,客户端只需传入参数,缺点是新增产品需要修改工厂类,违背开闭原则,适合产品类型极少的场景。


工厂方法模式 —— 让子类决定实例化哪个类(支付场景实战)

场景:电商系统支持支付宝和微信支付,不同支付方式有不同初始化流程。

// 抽象产品
public interface Payment { void pay(double amount); }
// 具体产品
public class Alipay implements Payment { 
    public void pay(double amount) { /* 支付宝SDK调用 */ }
}
public class WechatPay implements Payment { 
    public void pay(double amount) { /* 微信SDK调用 */ }
}
// 抽象工厂
public abstract class PaymentFactory {
    public abstract Payment createPayment();
    // 模板方法:公共流程
    public void processPayment(double amount) {
        Payment payment = createPayment();
        payment.pay(amount);
        // 记录审计日志...
    }
}
// 具体工厂:每个工厂负责一个产品
public class AlipayFactory extends PaymentFactory {
    public Payment createPayment() { return new Alipay(); }
}
public class WechatPayFactory extends PaymentFactory {
    public Payment createPayment() { return new WechatPay(); }
}
// 客户端:通过工厂实例获取
public class OrderService {
    private PaymentFactory paymentFactory;
    public OrderService(PaymentFactory factory) { this.paymentFactory = factory; }
    public void checkout(double amount) {
        paymentFactory.processPayment(amount);
    }
}

分析工厂方法模式将“创建”延迟到子类,客户端可以针对抽象工厂编程,在运行时动态切换具体实现,新增支付方式只需新增一个具体工厂类,完全不修改已有代码。


抽象工厂模式 —— 打造“产品族”的终极方案(跨平台UI案例)

场景:开发一个跨平台UI组件库,需要为Windows和Mac系统分别生成风格匹配的“按钮(Button)”和“文本框(Text)”。

// 抽象产品族
public interface Button { void render(); }
public interface TextField { void show(); }
// Windows产品族
public class WinButton implements Button { public void render() { /* 经典样式 */ } }
public class WinTextField implements TextField { public void show() { /* Windows风格 */ } }
// Mac产品族
public class MacButton implements Button { public void render() { /* 圆角样式 */ } }
public class MacTextField implements TextField { public void show() { /* Mac风格 */ } }
// 抽象工厂:声明创建一组相关产品的方法
public interface UIFactory {
    Button createButton();
    TextField createTextField();
}
// 具体工厂:维护整个产品族的兼容性
public class WinFactory implements UIFactory {
    public Button createButton() { return new WinButton(); }
    public TextField createTextField() { return new WinTextField(); }
}
public class MacFactory implements UIFactory {
    public Button createButton() { return new MacButton(); }
    public TextField createTextField() { return new MacTextField(); }
}
// 客户端:只需绑定一个工厂,保证UI风格统一
public class Application {
    private final UIFactory factory;
    public Application(UIFactory factory) { this.factory = factory; }
    public void buildUI() {
        Button b = factory.createButton();
        TextField t = factory.createTextField();
        // 组合布局...
    }
}

分析:抽象工厂确保同一产品族之间的相互兼容(不会出现Windows按钮配Mac文本框),它比工厂方法更抽象、更大型,适合处理多系列产品。


三大工厂模式对比与选型决策表

模式 核心思想 新增单个产品 新增整个产品族 使用场景
简单工厂 集中式 switch/if 修改工厂类 不支持 产品类型少且稳定
工厂方法 每个具体产品对应一个工厂 新增一个类 不可直接支持 单个产品线,扩展频繁
抽象工厂 工厂负责创建一组相关产品 修改抽象接口 新增一族类 跨平台、多主题等产品族场景

选型建议:如果只针对一种产品维度,首选工厂方法;若涉及多维度约束(如平台+外观),使用抽象工厂。注意避免过度设计:简单工厂能解决时不必强行使用抽象工厂。


高频面试问答与常见坑

Q1:工厂模式与策略模式的区别?

  • 工厂模式:创建对象,主要解决“如何创建”。
  • 策略模式:替换行为,主要解决“如何运行”,工厂通常结合策略来实现配置化策略切换。

Q2:Spring中BeanFactory和FactoryBean有什么区别?

  • BeanFactory是IoC容器的根接口,负责管理Bean生命周期。
  • FactoryBean是一个特殊Bean,自身作为工厂用来生产其他对象(典型的工厂方法模式应用)。

Q3:工厂模式如何违反依赖倒置原则?

  • 简单工厂中,客户端依赖于具体工厂类,建议客户端依赖抽象接口,工厂本身纳入接口管理。

常见坑

  1. 过度使用:产品种类固定且无扩展需求时,工厂反而增加复杂度。
  2. 静态工厂方法无法被继承:导致无法通过子类定制工厂行为。
  3. 多线程环境下未考虑线程安全:创建昂贵对象时应考虑双重检查锁或单例工厂。

如何在实际项目中优雅落地工厂模式

工厂模式并非银弹。合理的做法是“由重构而来,而非预先设计”,当发现代码中存在大量重复的new或switch条件判断出现增长趋势时,才将该处重构为工厂模式。

比如在微服务架构中,通过工厂类配合配置中心,可以动态创建不同类型的消息发送器(短信、邮件、推送),让业务代码完全不感知具体实现,结合反射枚举,可以构建“可扩展免修改”的简单工厂,大大提升灵活性。

请务必记住:工厂模式的核心是封装变化,而不是滥用接口,在团队中统一设计规范,并在代码评审时关注创建逻辑的耦合度,才能真正发挥其威力。


(文章结束)

抱歉,评论功能暂时关闭!