工厂方法模式简介及应用场景
工厂方法模式简介及应用场景:☀️☀️☀️
不积跬步无以至千里,不积小流无以成江河。欢迎交流~
1. 工厂方法模式(Factory Method Pattern)核心解读
工厂方法模式是创建型设计模式的核心之一,定义为:
定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
1.1 通俗理解
把“创建同类对象的不同实现”(比如创建不同品牌的手机:华为、苹果)抽离为独立的“工厂类”,主逻辑(业务代码)只需调用工厂接口获取对象,无需关心对象的具体创建细节。
1.2 核心角色(4个)
| 角色 | 作用 |
|---|---|
| 抽象产品(Product) | 定义所有具体产品必须实现的接口/抽象类(如手机的 call() 方法) |
| 具体产品(ConcreteProduct) | 实现抽象产品,封装产品的具体功能(如华为手机、苹果手机) |
| 抽象工厂(Factory) | 定义创建产品的接口,包含一个创建产品的抽象方法(如 createPhone()) |
| 具体工厂(ConcreteFactory) | 实现抽象工厂的创建方法,负责实例化具体产品(如华为工厂、苹果工厂) |
1.3 核心优势
开闭原则:新增产品时,仅需新增“具体产品类”和“具体工厂类”,无需修改原有工厂和业务代码;
解耦创建与使用:业务逻辑只依赖抽象产品和抽象工厂,不依赖具体实现,降低耦合度;
责任单一:工厂类专注于创建产品,业务类专注于使用产品,符合单一职责原则;
扩展性强:可在运行时通过切换具体工厂,动态创建不同的产品实例。
2. 工厂方法模式在Java中的典型示例(手机创建场景)
以“创建不同品牌手机”为例,对比不用工厂方法模式和用工厂方法模式的实现。
2.1 反例:不用工厂方法模式(耦合严重)
▼Java复制代码// 具体产品类 public class HuaweiPhone { public void call() { System.out.println("华为手机打电话"); } } public class IPhone { public void call() { System.out.println("苹果手机打电话"); } } // 业务逻辑直接依赖具体产品,耦合严重 public class PhoneService { // 新增手机品牌需修改此方法,违反开闭原则 public Object createPhone(String brand) { if ("HUAWEI".equals(brand)) { return new HuaweiPhone(); // 直接创建华为手机 } else if ("IPHONE".equals(brand)) { return new IPhone(); // 直接创建苹果手机 } else { throw new IllegalArgumentException("不支持的手机品牌"); } } public void usePhone(String brand) { // 需强制类型转换,代码臃肿 if ("HUAWEI".equals(brand)) { HuaweiPhone phone = (HuaweiPhone) createPhone(brand); phone.call(); } else if ("IPHONE".equals(brand)) { IPhone phone = (IPhone) createPhone(brand); phone.call(); } } } // 调用方 public class Client { public static void main(String[] args) { PhoneService service = new PhoneService(); service.usePhone("HUAWEI"); } }
问题:
新增品牌(如小米)需修改 createPhone() 和 usePhone() 方法,违反开闭原则;
需手动强制类型转换,代码冗余且易出错;
产品创建细节暴露在业务逻辑中,维护成本高。
2.2 正例:用工厂方法模式重构(大厂标准写法)
步骤1:定义抽象产品(手机接口)
▼Java复制代码// 所有手机的统一接口(抽象产品) public interface Phone { void call(); // 核心功能:打电话 }
步骤2:实现具体产品(各品牌手机)
▼Java复制代码// 华为手机(具体产品) public class HuaweiPhone implements Phone { @Override public void call() { System.out.println("【华为手机】发起通话,支持5G高清通话"); // 华为手机专属功能逻辑(如鸿蒙系统适配) } } // 苹果手机(具体产品) public class IPhone implements Phone { @Override public void call() { System.out.println("【苹果手机】发起通话,支持FaceTime联动"); // 苹果手机专属功能逻辑(如iOS生态适配) } }
步骤3:定义抽象工厂(手机工厂接口)
▼Java复制代码// 手机工厂的统一接口(抽象工厂) public interface PhoneFactory { Phone createPhone(); // 创建手机的抽象方法 }
步骤4:实现具体工厂(各品牌手机工厂)
▼Java复制代码// 华为手机工厂(具体工厂) public class HuaweiFactory implements PhoneFactory { @Override public Phone createPhone() { System.out.println("华为工厂:生产华为Mate系列手机"); // 手机创建前的初始化逻辑(如硬件检测、系统预装) return new HuaweiPhone(); } } // 苹果手机工厂(具体工厂) public class IPhoneFactory implements PhoneFactory { @Override public Phone createPhone() { System.out.println("苹果工厂:生产iPhone 16系列手机"); // 手机创建前的初始化逻辑(如iOS激活、隐私设置) return new IPhone(); } }
步骤5:定义环境类(统一调用入口)
▼Java复制代码// 封装工厂的统一调用入口 public class PhoneContext { // 工厂容器:缓存所有手机工厂 private static final Map<String, PhoneFactory> FACTORY_MAP = new HashMap<>(); // 静态初始化工厂 static { FACTORY_MAP.put("HUAWEI", new HuaweiFactory()); FACTORY_MAP.put("IPHONE", new IPhoneFactory()); } // 外部统一调用方法 public Phone createPhone(String brand) { PhoneFactory factory = FACTORY_MAP.get(brand); if (factory == null) { throw new IllegalArgumentException("不支持的手机品牌:" + brand); } return factory.createPhone(); } // 动态添加新工厂 public void addFactory(String brand, PhoneFactory factory) { FACTORY_MAP.put(brand, factory); } }
步骤6:调用方使用(极简)
▼Java复制代码public class Client { public static void main(String[] args) { PhoneContext context = new PhoneContext(); // 创建华为手机 Phone huaweiPhone = context.createPhone("HUAWEI"); huaweiPhone.call(); // 创建苹果手机 Phone iphone = context.createPhone("IPHONE"); iphone.call(); // 新增小米手机(无需修改原有代码) // context.addFactory("XIAOMI", new XiaomiFactory()); // Phone xiaomiPhone = context.createPhone("XIAOMI"); // xiaomiPhone.call(); } }
输出结果:
▼Plain复制代码华为工厂:生产华为Mate系列手机 【华为手机】发起通话,支持5G高清通话 苹果工厂:生产iPhone 16系列手机 【苹果手机】发起通话,支持FaceTime联动
2.3 Spring环境下的进阶写法(大厂实战)
结合注解+自动注入,无需手动维护工厂容器:
▼Java复制代码// 1. 定义工厂注解 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface PhoneFactoryAnnotation { String value(); // 手机品牌 } // 2. 具体产品交给Spring管理 @Component public class HuaweiPhone implements Phone { /* 实现方法同上 */ } @Component public class IPhone implements Phone { /* 实现方法同上 */ } // 3. 具体工厂添加注解+交给Spring管理 @PhoneFactoryAnnotation("HUAWEI") @Component public class HuaweiFactory implements PhoneFactory { @Autowired private HuaweiPhone huaweiPhone; @Override public Phone createPhone() { System.out.println("华为工厂:生产华为Mate系列手机"); return huaweiPhone; } } @PhoneFactoryAnnotation("IPHONE") @Component public class IPhoneFactory implements PhoneFactory { @Autowired private IPhone iphone; @Override public Phone createPhone() { System.out.println("苹果工厂:生产iPhone 16系列手机"); return iphone; } } // 4. 环境类自动加载工厂 @Component public class PhoneContext { private final Map<String, PhoneFactory> factoryMap; // Spring自动注入所有PhoneFactory类型的Bean public PhoneContext(List<PhoneFactory> factories) { factoryMap = new HashMap<>(); for (PhoneFactory factory : factories) { String brand = factory.getClass().getAnnotation(PhoneFactoryAnnotation.class).value(); factoryMap.put(brand, factory); } } // 创建手机方法(同上) public Phone createPhone(String brand) { PhoneFactory factory = factoryMap.get(brand); if (factory == null) { throw new IllegalArgumentException("不支持的手机品牌:" + brand); } return factory.createPhone(); } } // 5. 业务层调用 @Service public class OrderService { @Autowired private PhoneContext phoneContext; public void deliverPhone(String brand) { // 订单逻辑... Phone phone = phoneContext.createPhone(brand); System.out.println("配送手机:" + phone.getClass().getSimpleName()); phone.call(); } }
3. 工厂方法模式的典型应用场景(大厂高频)
除手机创建场景外,工厂方法模式在大厂项目中的核心应用:
3.1 多产品系列创建
场景:电商平台的商品创建(实物商品、虚拟商品)、物流系统的包裹创建(普通包裹、冷链包裹);
实现:每种商品/包裹对应“具体产品+具体工厂”,业务层通过抽象工厂统一创建。
3.2 算法/接口适配
场景:日志框架(Logback、Log4j 适配)、ORM框架(MyBatis 不同数据源适配);
实现:每种日志/数据源适配方式封装为工厂类,核心逻辑通过抽象工厂调用。
3.3 框架内置的工厂方法模式
大厂常用框架大量使用工厂方法模式:
JDK:Calendar(不同时区的日历实例)、NumberFormat(不同格式的数字格式化);
▼Java复制代码// Calendar的工厂方法应用 List<Integer> list = Arrays.asList(3,1,2); Calendar chinaCalendar = Calendar.getInstance(TimeZone.getTimeZone("Asia/Shanghai")); Calendar usCalendar = Calendar.getInstance(TimeZone.getTimeZone("America/New_York"));
Spring:BeanFactory(Bean创建工厂)、TransactionManager(不同数据源的事务管理器);
MyBatis:SqlSessionFactory(创建SqlSession实例,适配不同环境)。
4. 大厂为什么重视设计模式?
很多新手认为设计模式是“花架子”,但大厂对其重视程度极高,核心原因:
4.1 解决大规模代码的维护性问题
大厂项目代码量可达百万行,人员流动频繁:
无设计模式:代码是“面条式”new对象,新人接手需逐行读代码,改一行崩一片;
有设计模式:代码遵循统一规范(如工厂方法模式的“接口+实现”),新人快速理解,维护成本降低80%。
4.2 支撑高扩展的业务需求
大厂业务迭代极快(如电商每年新增N种商品类型):
无设计模式:新增功能需修改核心代码,风险高;
有设计模式:新增产品仅需加新类,符合“开闭原则”,上线风险几乎为0。
4.3 实现代码复用+标准化
大厂强调“不重复造轮子”:
工厂方法模式将对象创建逻辑封装为独立类,可在多模块复用;
设计模式是“程序员的通用语言”,说“这里用工厂方法模式”,团队全员理解代码结构,沟通成本降低。
4.4 适配高并发/高可用架构
工厂方法模式的“解耦”特性是高并发架构的基础:
商品创建场景:可按商品类型路由到不同工厂/服务器,实现分流;
数据库连接场景:可按业务模块切换不同连接池工厂,提升性能。
5. 总结
工厂方法模式核心:封装对象创建逻辑为独立工厂,解耦“创建逻辑”与“使用逻辑”;
典型应用:多产品创建、框架扩展、数据源适配等需动态创建对象的场景;
大厂价值:维护性(易读易改)、扩展性(新增产品不碰旧代码)、复用性(工厂类可复用);
避坑点:若仅创建单一产品且永不扩展,无需使用(避免过度设计);复杂多产品族场景,可升级为“抽象工厂模式”。
(注:文档部分内容可能由 AI 生成)
