关于三种工厂的设计模式总结
前言
简单工厂:只能提供一个工厂生产一种产品;
工厂方法:可以提供多个工厂生产一种产品;
抽象工厂:一个工厂可生产多种产品且可以提供多个工厂。


图片来源b站视频和评论区:《重学Java设计模式》第5章 抽象工厂模式_哔哩哔哩_bilibili
一、 简单工厂模式 (Simple Factory)
场景设定:你拥有一家全能小作坊。根据客户的指令,这家作坊既能做苹果手机,也能做小米手机。
1.1 代码实现
Java
// 1. 先规定什么是手机(产品接口)
public interface Phone {
void make(); // 制造手机
}
// 2. 具体的手机产品
public class IPhone implements Phone {
public void make() {
System.out.println("制造了一台苹果手机");
}
}
public class MiPhone implements Phone {
public void make() {
System.out.println("制造了一台小米手机");
}
}
// 3. 核心:简单工厂类
public class PhoneFactory {
// 客户传名字进来,工厂负责判断并实例化
public static Phone createPhone(String brand) {
if ("Apple".equals(brand)) {
return new IPhone();
} else if ("Xiaomi".equals(brand)) {
return new MiPhone();
} else {
return null; // 不支持的品牌
}
}
}
客户端调用(客户买手机):
客户不需要自己去 new IPhone(),直接找工厂要就行了。
Java
Phone myPhone = PhoneFactory.createPhone("Apple");
myPhone.make();
1.2 模式解析
- 核心逻辑 :重点看
PhoneFactory里的if-else。所有的"生杀大权"以及创建逻辑都集中在这一个静态方法里。 - 致命痛点 :如果明天客户说"我要买华为",你除了要新建一个
HuaweiPhone类,还必须 回头修改PhoneFactory的源代码,加上一段else if ("Huawei")。如果产品种类繁多,这个类会变成一个极易改出 Bug 的巨型判断炼狱,严重违背了开闭原则(OCP)。
二、 工厂方法模式 (Factory Method)
场景设定:随着作坊做大,为了方便管理,你决定拆分重组!成立专门的"苹果分厂"和"小米分厂"。现在客户想要什么牌子,直接去对应的专属分厂提货即可。
2.1 代码实现
Java
// 1. 产品类不变(依然有 Phone, IPhone, MiPhone)
// 2. 核心:抽象出一个"工厂的规矩"
public interface IFactory {
Phone createPhone(); // 所有的具体工厂都必须具备生产手机的方法
}
// 3. 具体的工厂类(专厂专办)
public class AppleFactory implements IFactory {
public Phone createPhone() {
return new IPhone(); // 苹果厂只造苹果
}
}
public class XiaomiFactory implements IFactory {
public Phone createPhone() {
return new MiPhone(); // 小米厂只造小米
}
}
客户端调用(客户买手机):
客户想买苹果,就先锁定苹果厂,再要手机。
Java
IFactory factory = new AppleFactory();
Phone myPhone = factory.createPhone();
myPhone.make();
2.2 模式解析
- 核心逻辑 :可怕的
if-else判断消失了!对象的创建职责被下放交给了具体的工厂实现类去完成。 - 巨大优势 :如果明天要新增"华为"产线,操作变得极其简单:直接新建一个
HuaweiPhone类和一个对应的HuaweiFactory类即可。原有的苹果和小米的代码一行都不用改 !这完美契合了开闭原则(对扩展开放,对修改封闭)。
三、 抽象工厂模式 (Abstract Factory)
场景设定 :品牌方的业务升级了,现在不仅仅卖手机,还要卖智能手表。他们要求你提供**"全家桶"服务。也就是说,苹果分厂不仅要造 iPhone,还要造 Apple Watch;华为分厂也要同时造 HuaweiPhone 和 HuaweiWatch。这就引入了"产品族(一套相关产品)"**的概念。
3.1 代码实现
Java
// 1. 多个产品接口(一套产品体系)
public interface Phone { void make(); }
public interface Watch { void make(); }
// 具体的苹果系产品
public class IPhone implements Phone { /*...*/ }
public class AppleWatch implements Watch { /*...*/ }
// 具体的华为系产品
public class HuaweiPhone implements Phone { /*...*/ }
public class HuaweiWatch implements Watch { /*...*/ }
// 2. 核心:超级大工厂接口(定义必须能造一整套生态的东西)
public interface AbstractFactory {
Phone createPhone(); // 必须能造手机
Watch createWatch(); // 必须能造手表
}
// 3. 具体的品牌全系代工厂
public class AppleFactory implements AbstractFactory {
public Phone createPhone() { return new IPhone(); }
public Watch createWatch() { return new AppleWatch(); }
}
public class HuaweiFactory implements AbstractFactory {
public Phone createPhone() { return new HuaweiPhone(); }
public Watch createWatch() { return new HuaweiWatch(); }
}
客户端调用(客户买一套生态电子产品):
Java
AbstractFactory factory = new AppleFactory(); // 我选定苹果全能代工厂
Phone myPhone = factory.createPhone(); // 拿到的绝对是 iPhone
Watch myWatch = factory.createWatch(); // 拿到的绝对是 AppleWatch
3.2 模式解析
- 核心逻辑 :看
AbstractFactory,里面不再只有一个create方法。它强制约束了底下的具体工厂(如AppleFactory)必须一次性提供整套的相关生态产品。 - 巨大优势 :它从代码架构层面保证了客户拿到手的一定是同一个生态 的配套组件。你选择调用
AppleFactory,产出的手机和手表就一定能完美配对,从根本上杜绝了"iPhone 强行搭配华为手表"这种逻辑错乱的产生。
总结
在实际项目架构中,选择哪种工厂模式并没有绝对的标准,核心在于平衡复杂度 与扩展性:
- 简单工厂 :
- 适用场景:产品类型很少,且业务预期内几乎不会再增加新产品(例如:数据库连接池仅支持 MySQL 和 Oracle 两种)。
- 优势:结构最简单,代码量最少,足够轻量。
- 工厂方法 :
- 适用场景:产品种类不确定,经常需要横向扩展增加新类型(例如:游戏引擎中的怪物种类,今天加哥布林,明天加史莱姆)。
- 优势:新增扩展极度平滑,完全不需要触碰老代码逻辑。
- 抽象工厂 :
- 适用场景 :产品不是单一出现的,而是成套、成体系(产品族)出现的(例如:开发跨平台 UI 界面库,Windows 风格必须对应自己的一套按钮和文本框,Mac 风格也有自己对应的一套)。
- 优势:强约束产品生态,保证整体风格和逻辑的统一,绝不乱套。