当前位置: 首页 > news >正文

设计模式-工厂模式:解耦对象创建的设计艺术

工厂模式详解:从制鞋厂看对象创建的艺术

如果把编程比作生产产品,那对象创建就像工厂生产商品。想象一下:如果一家鞋厂没有生产线规划,工人想到什么鞋就做什么鞋,原材料随意堆放,客户要一双运动鞋却给了皮鞋——这样的工厂注定混乱低效。

编程中直接用 new 关键字创建对象,就像这家混乱的鞋厂。而工厂模式,就是给鞋厂设计标准化生产线的“管理体系”。本文将通过“制鞋厂”的现实场景,通俗讲解简单工厂、工厂方法、抽象工厂三种模式的原理与应用。

一、为什么需要“工厂”?——从手工制鞋到标准化生产

假设你是一家小型鞋厂老板,一开始只有两种产品:运动鞋和皮鞋。工人直接手工制作,流程如下(对应代码直接 new 对象):

// 手工制鞋:客户要什么鞋,直接手工做
public class ShoeStore {public Shoe sellShoe(String type) {Shoe shoe;// 客户要运动鞋,就手工做一双if ("sports".equals(type)) {shoe = new SportsShoe();shoe.prepare(); // 准备材料:橡胶底、透气网布shoe.make();    // 制作:缝合、定型}// 客户要皮鞋,再手工做一双else if ("leather".equals(type)) {shoe = new LeatherShoe();shoe.prepare(); // 准备材料:牛皮、橡胶底shoe.make();    // 制作:裁剪、缝制}else {throw new RuntimeException("不生产这种鞋");}return shoe;}
}

随着订单增多,问题逐渐暴露:

  1. 工人太累:鞋店(ShoeStore)既要接待客户,又要负责做鞋,违背“专人专事”(单一职责原则)。
  2. 扩展困难:想新增“凉鞋”时,要修改鞋店的制作流程(sellShoe 方法),可能影响已有鞋类的生产(违背开闭原则)。
  3. 质量不稳定:不同工人做的同一款鞋工艺不一,比如运动鞋的橡胶底厚度不统一。

解决办法很简单:建一条标准化生产线(工厂),专门负责做鞋,鞋店只负责卖鞋。这就是工厂模式的核心思想——将“做鞋(创建对象)”和“卖鞋(使用对象)”分离

二、简单工厂:小型制鞋流水线

场景模拟

你的鞋厂规模扩大,决定建一条流水线(简单工厂),专门负责生产运动鞋和皮鞋。流水线根据订单类型(参数)决定生产哪种鞋,工人只需按流程操作。

模式定义

简单工厂是一个集中化的生产车间,通过接收“产品类型”参数,决定生产哪种产品。客户端只需告诉工厂“要什么”,无需知道“怎么做”。

代码实现(制鞋场景)

// 1. 抽象产品:鞋子(定义所有鞋的通用属性)
public abstract class Shoe {protected String name; // 鞋名protected String sole; // 鞋底材料protected String upper; // 鞋面材料// 抽象方法:准备材料(不同鞋材料不同)public abstract void prepare();// 通用方法:制作(所有鞋制作流程类似)public void make() {System.out.println("制作" + name + ":缝合鞋底与鞋面");}// 通用方法:包装public void box() {System.out.println("将" + name + "装入包装盒");}
}// 2. 具体产品:运动鞋
public class SportsShoe extends Shoe {public SportsShoe() {name = "运动鞋";}@Overridepublic void prepare() {sole = "橡胶底(防滑)";upper = "透气网布";System.out.println("准备" + name + "材料:" + sole + "、" + upper);}
}// 2. 具体产品:皮鞋
public class LeatherShoe extends Shoe {public LeatherShoe() {name = "皮鞋";}@Overridepublic void prepare() {sole = "橡胶底(耐磨)";upper = "牛皮";System.out.println("准备" + name + "材料:" + sole + "、" + upper);}
}// 3. 简单工厂:制鞋流水线
public class ShoeFactory {// 根据订单类型生产鞋子public static Shoe createShoe(String type) {Shoe shoe = null;if ("sports".equals(type)) {shoe = new SportsShoe();} else if ("leather".equals(type)) {shoe = new LeatherShoe();} else {throw new RuntimeException("不生产" + type + "类型的鞋");}// 工厂统一完成制作流程(准备→制作→包装)shoe.prepare();shoe.make();shoe.box();return shoe;}
}// 4. 客户端:鞋店(只负责卖鞋,不关心制作)
public class ShoeStore {public Shoe sellShoe(String type) {System.out.println("客户下单:" + type + "鞋");// 直接从工厂拿货,无需自己做Shoe shoe = ShoeFactory.createShoe(type);System.out.println("客户取走" + shoe.name + "\n");return shoe;}public static void main(String[] args) {ShoeStore store = new ShoeStore();store.sellShoe("sports"); // 卖运动鞋store.sellShoe("leather"); // 卖皮鞋}
}

运行结果

客户下单:sports鞋
准备运动鞋材料:橡胶底(防滑)、透气网布
制作运动鞋:缝合鞋底与鞋面
将运动鞋装入包装盒
客户取走运动鞋客户下单:leather鞋
准备皮鞋材料:橡胶底(耐磨)、牛皮
制作皮鞋:缝合鞋底与鞋面
将皮鞋装入包装盒
客户取走皮鞋

解决的问题

  • 鞋店(ShoeStore)彻底解放,只负责销售,不用关心制作流程。
  • 制作流程标准化(所有鞋都经过“准备→制作→包装”),质量更稳定。
  • 新增鞋类时,鞋店代码无需修改(符合开闭原则)。

三、工厂方法:按产品类型分设车间

场景升级

你的鞋厂名气越来越大,决定新增“凉鞋”产品线。但问题来了:运动鞋需要防滑测试,皮鞋需要皮质检测,凉鞋需要防水测试——简单工厂的一条流水线无法满足不同产品的特殊流程,效率低下。

解决办法:按产品类型分设车间——运动鞋车间专门生产运动鞋,皮鞋车间专门生产皮鞋,每个车间有自己的特殊工艺。

模式定义

工厂方法为每种产品设立专属工厂,每个工厂只生产一种产品,并负责该产品的全部生产流程(包括特殊工艺)。客户端通过选择不同工厂来获取对应产品。

代码实现(分车间生产)

// 1. 抽象产品:鞋子(同上,新增特殊工艺方法)
public abstract class Shoe {// ... 原有代码 ...public abstract void specialProcess(); // 特殊工艺(不同鞋不一样)
}// 2. 具体产品:运动鞋(新增防滑测试)
public class SportsShoe extends Shoe {// ... 原有代码 ...@Overridepublic void specialProcess() {System.out.println("运动鞋特殊工艺:防滑测试");}
}// 2. 具体产品:皮鞋(新增皮质检测)
public class LeatherShoe extends Shoe {// ... 原有代码 ...@Overridepublic void specialProcess() {System.out.println("皮鞋特殊工艺:皮质检测");}
}// 3. 抽象工厂:鞋厂车间接口(定义生产流程)
public interface ShoeFactory {Shoe produceShoe(); // 生产鞋子
}// 4. 具体工厂:运动鞋车间
public class SportsShoeFactory implements ShoeFactory {@Overridepublic Shoe produceShoe() {System.out.println("===== 运动鞋车间 =====");Shoe shoe = new SportsShoe();shoe.prepare();shoe.make();shoe.specialProcess(); // 执行运动鞋特殊工艺shoe.box();return shoe;}
}// 4. 具体工厂:皮鞋车间
public class LeatherShoeFactory implements ShoeFactory {@Overridepublic Shoe produceShoe() {System.out.println("===== 皮鞋车间 =====");Shoe shoe = new LeatherShoe();shoe.prepare();shoe.make();shoe.specialProcess(); // 执行皮鞋特殊工艺shoe.box();return shoe;}
}// 5. 客户端:鞋店(根据客户需求选择车间)
public class ShoeStore {// 传入具体工厂,而非产品类型public Shoe sellShoe(ShoeFactory factory) {System.out.println("客户下单,通知对应车间生产");Shoe shoe = factory.produceShoe();System.out.println("客户取走" + shoe.name + "\n");return shoe;}public static void main(String[] args) {ShoeStore store = new ShoeStore();// 卖运动鞋:找运动鞋车间store.sellShoe(new SportsShoeFactory());// 卖皮鞋:找皮鞋车间store.sellShoe(new LeatherShoeFactory());}
}

运行结果

客户下单,通知对应车间生产
===== 运动鞋车间 =====
准备运动鞋材料:橡胶底(防滑)、透气网布
制作运动鞋:缝合鞋底与鞋面
运动鞋特殊工艺:防滑测试
将运动鞋装入包装盒
客户取走运动鞋客户下单,通知对应车间生产
===== 皮鞋车间 =====
准备皮鞋材料:橡胶底(耐磨)、牛皮
制作皮鞋:缝合鞋底与鞋面
皮鞋特殊工艺:皮质检测
将皮鞋装入包装盒
客户取走皮鞋

新增产品的优势

当需要新增“凉鞋”时,只需添加两个类,原有代码完全不用改:

// 新增具体产品:凉鞋
public class Sandal extends Shoe {public Sandal() { name = "凉鞋"; }@Overridepublic void prepare() { /* 准备塑料鞋底和帆布 */ }@Overridepublic void specialProcess() {System.out.println("凉鞋特殊工艺:防水测试");}
}// 新增具体工厂:凉鞋车间
public class SandalFactory implements ShoeFactory {@Overridepublic Shoe produceShoe() {System.out.println("===== 凉鞋车间 =====");// ... 生产流程 ...return new Sandal();}
}// 客户端直接使用新车间
store.sellShoe(new SandalFactory()); // 无需修改鞋店代码

这完美符合“开闭原则”——扩展开放,修改关闭

四、抽象工厂:按品牌设立生产线

场景再升级

你的鞋厂开始代工国际品牌,比如耐克(Nike)和阿迪达斯(Adidas)。每个品牌不仅有自己的运动鞋,还有配套的鞋盒、标签——这些产品需要风格统一(比如耐克的logo、配色)。

此时需要解决的问题:确保同一品牌的系列产品风格一致(如耐克运动鞋+耐克鞋盒+耐克标签)。这就是抽象工厂要解决的“产品族”问题。

模式定义

抽象工厂用于生产一系列相互关联的产品族(如“耐克品牌的鞋+鞋盒+标签”)。每个具体工厂对应一个品牌,负责生产该品牌的所有配套产品,确保风格统一。

代码实现(品牌代工场景)

// 1. 抽象产品族:鞋子、鞋盒、标签(同一品牌需风格统一)
public interface Shoe { void showBrand(); }
public interface ShoeBox { void showBrand(); }
public interface Label { void showBrand(); }// 2. 具体产品族1:耐克(Nike)
public class NikeShoe implements Shoe {@Overridepublic void showBrand() { System.out.println("耐克运动鞋(勾形logo)"); }
}
public class NikeBox implements ShoeBox {@Overridepublic void showBrand() { System.out.println("耐克鞋盒(红色)"); }
}
public class NikeLabel implements Label {@Overridepublic void showBrand() { System.out.println("耐克标签(材质:纸质)"); }
}// 2. 具体产品族2:阿迪达斯(Adidas)
public class AdidasShoe implements Shoe {@Overridepublic void showBrand() { System.out.println("阿迪运动鞋(三道杠logo)"); }
}
public class AdidasBox implements ShoeBox {@Overridepublic void showBrand() { System.out.println("阿迪鞋盒(蓝色)"); }
}
public class AdidasLabel implements Label {@Overridepublic void showBrand() { System.out.println("阿迪标签(材质:布质)"); }
}// 3. 抽象工厂:品牌生产线(定义生产所有配套产品的接口)
public interface BrandFactory {Shoe createShoe();ShoeBox createShoeBox();Label createLabel();
}// 4. 具体工厂1:耐克生产线
public class NikeFactory implements BrandFactory {@Overridepublic Shoe createShoe() { return new NikeShoe(); }@Overridepublic ShoeBox createShoeBox() { return new NikeBox(); }@Overridepublic Label createLabel() { return new NikeLabel(); }
}// 4. 具体工厂2:阿迪生产线
public class AdidasFactory implements BrandFactory {@Overridepublic Shoe createShoe() { return new AdidasShoe(); }@Overridepublic ShoeBox createShoeBox() { return new AdidasBox(); }@Overridepublic Label createLabel() { return new AdidasLabel(); }
}// 5. 客户端:代工厂组装车间(按品牌组装产品)
public class AssemblyLine {private Shoe shoe;private ShoeBox box;private Label label;// 传入品牌工厂,确保所有产品风格统一public AssemblyLine(BrandFactory factory) {this.shoe = factory.createShoe();this.box = factory.createShoeBox();this.label = factory.createLabel();}public void assemble() {System.out.println("开始组装品牌产品:");shoe.showBrand();box.showBrand();label.showBrand();System.out.println("组装完成\n");}public static void main(String[] args) {// 组装耐克产品(所有组件都是耐克)AssemblyLine nikeLine = new AssemblyLine(new NikeFactory());nikeLine.assemble();// 组装阿迪产品(所有组件都是阿迪)AssemblyLine adidasLine = new AssemblyLine(new AdidasFactory());adidasLine.assemble();}
}

运行结果

开始组装品牌产品:
耐克运动鞋(勾形logo)
耐克鞋盒(红色)
耐克标签(材质:纸质)
组装完成开始组装品牌产品:
阿迪运动鞋(三道杠logo)
阿迪鞋盒(蓝色)
阿迪标签(材质:布质)
组装完成

核心价值

抽象工厂确保了同一产品族的兼容性——你永远不会得到“耐克运动鞋+阿迪鞋盒”的组合,这在需要统一风格的场景(如品牌代工、跨平台UI组件)中至关重要。

五、三种工厂模式的对比:该用哪一种?

模式类型现实场景类比核心优势适合情况
简单工厂小型流水线(一条线生产多种鞋)实现简单,集中管理创建逻辑产品少且变化不频繁(如只有2-3种鞋)
工厂方法按产品分车间(运动鞋车间、皮鞋车间)扩展灵活,符合开闭原则产品多或经常新增产品(如不断推出新鞋型)
抽象工厂按品牌分生产线(耐克线、阿迪线)保证产品族的一致性需要生产系列配套产品(如鞋+鞋盒+标签)

用一句话总结:

  • 简单工厂是“一厂多品”
  • 工厂方法是“一厂一品”
  • 抽象工厂是“一厂一族”

六、工厂模式的设计本质

从制鞋厂的例子可以看出,工厂模式的核心不是“创建工厂类”,而是建立“创建者”与“产品”之间的隔离带

  • 让“创建者”(工厂)专注于“如何生产”(封装变化的创建逻辑)。
  • 让“使用者”(客户端)专注于“如何使用”(依赖稳定的抽象接口)。

这种隔离带来了两大好处:

  1. 灵活性:更换产品时,只需更换工厂,无需修改使用者代码(如鞋店换个车间就能卖新鞋)。
  2. 稳定性:产品创建逻辑的变化不会影响使用者(如车间改进工艺,鞋店卖鞋流程不变)。

总结:从鞋厂到代码的启示

工厂模式就像制鞋厂的管理体系:

  • 小作坊(简单场景)用简单工厂,快速高效。
  • 多产品线的中型工厂用工厂方法,灵活扩展。
  • 生产系列产品的大型企业用抽象工厂,保证一致性。

在代码中,当发现“对象创建逻辑散落在业务代码中”“新增产品需要修改多处代码”时,不妨想想制鞋厂的例子——是时候引入工厂模式,给你的代码建一条“标准化生产线”了。


Studying will never be ending.

▲如有纰漏,烦请指正~~

http://www.dtcms.com/a/511377.html

相关文章:

  • UVa 1660 Cable TV Network
  • 使用 Python 语言 从 0 到 1 搭建完整 Web UI自动化测试学习系列 20--PO(POM) 设计模式和用例撰写
  • 网站建设年度计划申请了域名 网站怎么建设呢
  • 《黄雀》电视剧总结
  • 云计算与服务器概述
  • 【Java Web学习 | 第1篇】前端 - HTML
  • Jenkins流水线项目发布
  • 网站优化需要做什么烟台网站建设比较大的
  • CAN入侵检测系统IDS不行,用扩充白名单机制保证汽车功能安全需求
  • 微软Teams的Media bypass的介绍
  • 分布式一致性
  • 使用微软Agent Framework .NET构建智能代理应用
  • MOSHELL (10) : COLI 交互
  • 九江网站开发wordpress适合seo
  • 【JavaScript】some方法的详解与实战
  • 买机票便宜网站建设分站式二手车网站源码
  • windows配置hadoop环境
  • Java中的单例模式
  • K8s部署,新版本
  • LXC容器操作实战【Linux】
  • CAN总线: 仲裁
  • ⸢ 捌-Ⅱ⸥⤳ 可信纵深防御应用实践:软件供应链、数据滥用、安全加固
  • Linux Bash(二)
  • 上海建设单位工程备案网站宜宾网站建设网站
  • AI: 生成Android自我学习路线规划与实战
  • 项目实践2—全球证件智能识别系统(Qt客户端开发+FastAPI后端人工智能服务开发)
  • 百度面试题解析:新生代分区、垃圾回收算法、虚拟机栈和类加载(四)
  • AIDC爆火,储能企业跨界抢滩AI能源“新战场”
  • h5游戏免费下载:飞越天空之城
  • 温州市建设厅网站首页什么网站可以自己做房子设计图