引言
很多初学者分不清简单工厂、工厂方法、抽象工厂,其实它们并不是三个孤立的设计模式,而是同一条演进路线:简单工厂 → 工厂方法 → 抽象工厂。简单工厂把创建逻辑抽离,却堆满 if-else;工厂方法把工厂也抽象掉,新增产品不改老代码;抽象工厂则解决一族产品的配套创建问题。每一步升级,都是用更高复杂度换取更强扩展性。
目录
一. 简单工厂
二. 工厂方法
三. 抽象工厂
实战:软考真题
一. 简单工厂
1. 结构图

2. 代码实现
①创建抽象类、具体类
abstract class Product{
public abstract void info();
}
class ProductA extends Product{
@Override
public void info() {
System.out.println("产品的信息:A");
}
}
class ProductB extends Product{
@Override
public void info() {
System.out.println("产品的信息:B");
}
}
②创建工厂类
class Factory{
public static Product createProduct(String type){
Product product = null;
switch (type){
case "A":
product = new ProductA();
break;
case "B":
product = new ProductB();
break;
default:
System.out.println("没有 "+type+" 类型的产品");
break;
}
return product;
}
}
测试一下
//简单工厂模式
public class SimpleFactory {
public static void main(String[] args) {
Product productA = Factory.createProduct("A");
productA.info();
Product productB = Factory.createProduct("B");
productB.info();
Product productC = Factory.createProduct("C");
productC.info();
}
}
运行结果如下:

3. 解读
| 1 | 返回类型是抽象类,实际值是具体类 | 编译期类型为父类型,运行期类型为子类,本质是多态(向上转型) | public static Product createProduct(…) 返回 Product,实际 new ProductA() |
| 2 | 父 = 子,多态思想 | 客户端只依赖抽象 Product,不依赖任何具体产品类 | Product productA = Factory.createProduct("A"); |
| 3 | 封装创建,客户端不再 new | new 被关进工厂,客户端与具体类解耦 | 客户端只写 Factory.createProduct("A"),不出现 new ProductA() |
| 4 | 集中判断(switch/if-else) | 工厂内部集中决定创建哪个产品,一目了然 | switch(type){ case "A": … case "B": … } |
| 5 | 静态方法,调用方便 | 不用先创建工厂对象,直接类名调用 | public static Product createProduct(…) |
| 6 | 客户端只认“能干什么”,不认“是谁” | 客户端只调抽象方法,具体执行哪个由运行时对象决定 | productA.info(); 只调抽象方法 |
| 7 | switch 是特征,也是软肋 | 新增产品要改 switch,违反开闭原则,这正是被工厂方法取代的原因 | 每加一个产品,就要加一个 case |
| 8 | 静态方法无法被继承重写 | 简单直接,但工厂无法扩展,这是“简单”的代价 | static 方法不能被 override |
4. 最大的缺点:违反“开放—封闭”原则

现在我们的工厂类只支持创建A、B两种产品,但是后续加入产品C时,遇到如下问题:

说白了,此时我们由于新加了一个产品C,导致不得不修改工厂类的代码。这的确违反了“开放—封闭”原则。因为我们通常对扩展是开放的,对修改是关闭的。对应到此处就是,你扩展了产品C是没问题的,但是不能修改工厂类的代码。
由于简单工厂模式存在上述缺陷,因此引出下面的工厂方法模式.
二. 工厂方法
1. 结构图

2. 代码实现
①创建产品接口、实现类
interface Product{
public void info();
}
class ProductA implements Product{
@Override
public void info() {
System.out.println("产品的信息:A");
}
}
class ProductB implements Product{
@Override
public void info() {
System.out.println("产品的信息:B");
}
}
②创建工厂接口、实现类
interface Factory{
public Product createProduct();
}
class FactoryA implements Factory{
@Override
public Product createProduct() {
return new ProductA();
}
}
class FactoryB implements Factory{
@Override
public Product createProduct() {
return new ProductB();
}
}
测试一下
//工厂方法
public class test {
public static void main(String[] args) {
Factory factoryA = new FactoryA();
Product productA = factoryA.createProduct();
productA.info();
Factory factoryB = new FactoryB();
Product productB = factoryB.createProduct();
productB.info();
}
}
运行效果:

3. 解读
| 1 | 工厂也抽象成接口 | 工厂不再是一个具体类,而是一个接口,定义创建产品的规范 | interface Factory { Product createProduct(); } |
| 2 | 每个产品配一个专属工厂 | 一个具体产品对应一个具体工厂,职责单一 | FactoryA → ProductA,FactoryB → ProductB |
| 3 | 返回类型是抽象产品,实际值是具体产品 | 和简单工厂一样,编译期是父类型,运行期是子类,本质是多态 | public Product createProduct() 返回 Product,实际 new ProductA() |
| 4 | 父 = 子,多态思想 | 客户端只依赖 Product 和 Factory 两个抽象,不依赖具体类 | Product productA = factoryA.createProduct(); |
| 5 | 客户端不再 switch 判断 | 简单工厂的 switch 被“多态分发”取代,选哪个工厂由客户端决定 | 客户端选 new FactoryA() 还是 new FactoryB() |
| 6 | 新增产品不改老代码 | 加一个产品 = 加一个产品类 + 加一个工厂类,符合开闭原则 | 新增 ProductC 只需加 ProductC + FactoryC |
| 7 | 代价:类数量翻倍 | 每个产品都要配一个工厂,类的数量成对增长 | N 个产品 → N 个产品类 + N 个工厂类 |
| 8 | 只解决“一个产品等级” | 工厂接口里只有一个 createProduct(),搞不定产品族 | 无法保证“按钮+复选框”配套创建 |
4. 优点:遵循“开放—封闭”原则
举例:我们新加一个产品C,只需要增加一个对应的专属工厂类即可,而无需修改任何之前的代码(也就是对拓展开放,对修改关闭)




可见,我们新增一个产品时,只需要新增对应的类、具体工厂类即可,而无需修改之前的任何代码,这就遵守了“开放—封闭”原则(即:对新增开放,对修改关闭。说白了就是当新增一部分功能时,可以新增代码,但尽量不要修改之前的代码)。
5. 补充

这个结构图,其实和上面的结构图是一个意思,只不过画的方式有区别,但表达的意思是一样的。
下面的事项看看就行,了解即可。

三. 抽象工厂
1. 结构图

2. 代码实现
// ========== 抽象产品族 ==========
// 产品等级 1:按钮
interface Button {
void render();
}
// 产品等级 2:复选框
interface Checkbox {
void render();
}
// ========== 具体产品:Windows 家族 ==========
class WindowsButton implements Button {
@Override
public void render() {
System.out.println("渲染 Windows 按钮");
}
}
class WindowsCheckbox implements Checkbox {
@Override
public void render() {
System.out.println("渲染 Windows 复选框");
}
}
// ========== 具体产品:Mac 家族 ==========
class MacButton implements Button {
@Override
public void render() {
System.out.println("渲染 Mac 按钮");
}
}
class MacCheckbox implements Checkbox {
@Override
public void render() {
System.out.println("渲染 Mac 复选框");
}
}
// ========== 抽象工厂:定义一族产品的创建接口 ==========
interface GUIFactory {
Button createButton();
Checkbox createCheckbox();
}
// ========== 具体工厂:Windows 工厂 ==========
class WindowsFactory implements GUIFactory {
@Override
public Button createButton() {
return new WindowsButton();
}
@Override
public Checkbox createCheckbox() {
return new WindowsCheckbox();
}
}
// ========== 具体工厂:Mac 工厂 ==========
class MacFactory implements GUIFactory {
@Override
public Button createButton() {
return new MacButton();
}
@Override
public Checkbox createCheckbox() {
return new MacCheckbox();
}
}
// ========== 客户端 ==========
public class AbstractFactoryTest {
public static void main(String[] args) {
// 只选一次工厂,之后创建的所有组件都自动配套
GUIFactory factory = new WindowsFactory();
// GUIFactory factory = new MacFactory(); // 换一行就切换整个产品族
Button button = factory.createButton();
Checkbox checkbox = factory.createCheckbox();
button.render();
checkbox.render();
}
}
3. 解读
| 1 | 保证产品族内的一致性 | 同一个工厂创建出的产品天然配套,不会出现“Windows 按钮配 Mac 复选框” | WindowsFactory 只会产出 WindowsButton + WindowsCheckbox |
| 2 | 客户端与具体产品解耦 | 客户端只依赖抽象 Button、Checkbox、GUIFactory,不碰任何具体类 | 客户端代码里没有 new WindowsButton() |
| 3 | 切换产品族非常方便 | 换一个工厂,整个产品族一起换,只改一行 | new WindowsFactory() → new MacFactory() |
| 4 | 符合开闭原则(对新增产品族而言) | 新增一个产品族(如 Linux 风格),只需加一套产品类 + 一个工厂类,不改老代码 | 新增 LinuxButton、LinuxCheckbox、LinuxFactory |
| 5 | 职责清晰,符合单一职责 | 每个具体工厂只负责创建自己那一族产品 | MacFactory 只造 Mac 系列 |
| 6 | 便于统一管理与扩展 | 一族产品的创建逻辑集中在一个工厂里,规范统一 | 所有 Mac 组件的创建都归 MacFactory |
4. 优点
抽象工厂最大的优点:保证一族产品配套一致,且切换产品族只需换一个工厂。
5. 补充

实战:软考真题
题目


以上就是本篇文章的全部内容,喜欢的话可以留个免费的关注呦~~~
网硕互联帮助中心

评论前必须登录!
注册