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

【软件设计模式】工厂方法与抽象工厂

前言:上学期学了一门课——《软件设计模式与体系结构》,当时觉得没什么用,我实际开发中也没使用过,但是刚好报了软件设计师考试,其中也有这部分知识,同时也为了期末考,也就认真学了这门课,理论学的挺6的,发现还挺有意思,刚好最近在优化我的项目,其中也使用到了一些设计模式,想着再系统地复习一遍,记录一下笔记。

一、工厂方法模式

1.概念

        工厂方法模式(Factory Method Pattern)是一种类创建型模式,其核心思想是将对象的实例化延迟到子类。通过定义一个创建对象的接口,但由子类决定具体实例化哪个类。

        工厂方法模式可以简单理解为:“让专门的‘工厂’来生产‘产品’,你只需要告诉工厂你要什么,不用管具体怎么做出来”

打个生活中的比方:
你去咖啡店买咖啡(这就是 “你” 作为客户端),咖啡店(相当于 “抽象工厂”)有不同的制作区域:美式咖啡区(具体工厂 A)、拿铁区(具体工厂 B)。
你不需要自己动手做咖啡(不用关心咖啡的具体制作步骤),只需要告诉店员你要美式还是拿铁,对应的制作区就会给你做好(具体工厂生产具体产品)。
如果后来咖啡店新增了卡布奇诺(新的产品),只需要再开一个卡布奇诺制作区(新的具体工厂),原来的区域和你点单的方式都不用变。

        核心就是:把 “创建东西” 的工作交给专门的 “工厂”,你只需要用,不用知道东西是怎么造出来的。而且以后想换品种,直接换个工厂就行,不用改自己的代码

核心目标

  • 解耦对象的创建与使用,客户端无需关心具体产品类的实例化细节。

  • 支持扩展,符合开闭原则(新增产品时无需修改原有代码)。

2.工厂方法模式的结构

工厂方法模式包含以下4个角色:

角色职责示例(书写工具案例)
抽象产品(Product)定义产品的规范,描述通用功能。WritingTool(书写工具接口)
具体产品(ConcreteProduct)实现抽象产品的接口,提供具体功能。PenBallPenBrushPen
抽象工厂(AbstractFactory)声明工厂方法(如createProduct()),用于创建产品对象。WritingToolFactory
具体工厂(ConcreteFactory)实现抽象工厂的工厂方法,返回具体产品的实例。PenFactoryBallPenFactory

典型代码结构

抽象工厂类

public interface LoggerFactory {Logger createLogger(); // 工厂方法
}

具体工厂类

public class FileLoggerFactory implements LoggerFactory {@Overridepublic Logger createLogger() {return new FileLogger(); // 返回具体产品}
}

3.工厂方法模式的优缺点

优点缺点
1. 隐藏实例化细节:客户端只依赖抽象接口,无需关心具体类。1. 类数量增加:每新增一个产品需新增一个工厂类,导致系统复杂度上升。
2. 符合开闭原则:新增产品时只需扩展子类,无需修改原有代码。2. 理解难度提高:引入了抽象层,增加了系统设计复杂性。
3. 灵活扩展:支持动态切换产品(如通过配置文件)。

4.适用环境

  1. 客户端无需知道具体类名:只需通过工厂接口获取对象(如日志记录器、数据库连接器等)。

  2. 需要动态扩展产品:系统未来可能新增产品类型(如新增日志存储方式)。

  3. 解耦需求:避免客户端代码与具体类直接耦合,提高代码可维护性。

典型场景

  • 日志记录器(文件日志、数据库日志)。

  • 跨平台UI组件(不同操作系统下的按钮、窗口)。

  • 支付系统(支付宝、微信支付等不同支付方式)。

5.工厂方法模式的应用实例

说明:工厂方法模式就像不同的咖啡制作工坊,每个工坊专注于制作一种咖啡。

// 抽象产品:咖啡
public interface Coffee {// 制作咖啡的方法void make();
}// 具体产品:拿铁咖啡
public class LatteCoffee implements Coffee {@Overridepublic void make() {System.out.println("制作一杯拿铁咖啡");}
}// 具体产品:美式咖啡
public class AmericanCoffee implements Coffee {@Overridepublic void make() {System.out.println("制作一杯美式咖啡");}
}// 抽象工厂:咖啡工厂
public interface CoffeeFactory {// 生产咖啡的方法Coffee createCoffee();
}// 具体工厂:拿铁咖啡工厂
public class LatteCoffeeFactory implements CoffeeFactory {@Overridepublic Coffee createCoffee() {return new LatteCoffee();}
}// 具体工厂:美式咖啡工厂
public class AmericanCoffeeFactory implements CoffeeFactory {@Overridepublic Coffee createCoffee() {return new AmericanCoffee();}
}// 客户端
public class Client {public static void main(String[] args) {// 创建美式咖啡工厂CoffeeFactory americanFactory = new AmericanCoffeeFactory();// 制作美式咖啡Coffee americanCoffee = americanFactory.createCoffee();americanCoffee.make();  // 输出:制作一杯美式咖啡// 创建拿铁咖啡工厂CoffeeFactory latteFactory = new LatteCoffeeFactory();// 制作拿铁咖啡Coffee latteCoffee = latteFactory.createCoffee();latteCoffee.make();  // 输出:制作一杯拿铁咖啡}
}

在这个例子中:

  • 每个咖啡种类(美式、拿铁)是具体产品
  • 每个咖啡工厂只生产一种咖啡
  • 客户端只需选择相应的工厂,无需知道咖啡的具体制作过程
  • 如果要新增咖啡种类,只需添加新的具体产品和对应的工厂

6.总结

  • 核心思想延迟实例化到子类,通过抽象接口隔离客户端与具体产品。

  • 关键设计原则:依赖倒置原则(DIP)、开闭原则(OCP)。

  • 适用性:适合需要灵活扩展、解耦的场景,但需权衡类数量增加的代价。

通过工厂方法模式,可以构建高扩展性、低耦合的系统架构,尤其适合框架设计和中间件开发。

二、抽象工厂模式

1.概念

        抽象工厂模式(Abstract Factory Pattern)是一种对象创建型模式,用于创建一系列相关或相互依赖的对象(即一个产品族),而无需指定它们的具体类。

        抽象工厂模式可以简单理解为:“一个‘超级工厂’,专门生产一系列配套的产品,这些产品天生就适合搭配使用”

打个生活比方:
就像买电脑时,你可以选 “Intel 套装” 或 “AMD 套装”——

  • Intel 套装里的 CPU、主板、显卡都是 Intel 体系的,它们彼此兼容;
  • AMD 套装里的 CPU、主板、显卡都是 AMD 体系的,也能完美搭配。

        你不用自己逐个挑零件(不用担心买的 CPU 和主板不兼容),只需告诉商家要哪个 “套装系列”,商家就会给你一套能一起用的配件。如果以后出了新的 “ARM 套装”,商家只需新增这个系列的生产能力,你买的方式还是一样的。

        核心就是:用一个工厂生产一整套 “互相匹配” 的产品,你要啥系列就选啥工厂,不用操心内部零件是否兼容

核心目标

  • 封装一组具有共同主题的独立产品

  • 确保客户端始终使用同一产品族中的对象

  • 支持新增产品族(符合开闭原则),但不支持新增产品类型(违反开闭原则)。

2.抽象工厂模式的结构

抽象工厂模式包含以下4个角色:

角色职责示例(界面皮肤库)
抽象产品(AbstractProduct)定义一类产品的接口(如按钮、文本框)。ButtonTextField
具体产品(ConcreteProduct)实现抽象产品接口,属于同一产品族(如Spring风格按钮、Summer风格文本框)。SpringButtonSummerTextField
抽象工厂(AbstractFactory)声明一组创建产品的方法,每个方法对应一个产品等级结构。SkinFactory
具体工厂(ConcreteFactory)实现抽象工厂的方法,生成同一产品族的所有具体产品。SpringSkinFactorySummerSkinFactory

典型代码结构

抽象工厂接口

public interface SkinFactory {Button createButton();TextField createTextField();ComboBox createComboBox();
}

具体工厂类

public class SpringSkinFactory implements SkinFactory {@Overridepublic Button createButton() { return new SpringButton(); }@Overridepublic TextField createTextField() { return new SpringTextField(); }// ...其他产品
}

3.抽象工厂模式的优缺点

优点缺点
1. 隔离具体类:客户端仅依赖抽象接口,与具体实现解耦。1. 难以扩展新产品类型:新增产品等级需修改所有工厂类,违反开闭原则。
2. 保证产品族一致性:客户端始终使用同一主题的产品。2. 系统复杂度高:需设计大量接口和类。
3. 支持新增产品族:扩展新主题(如新增Winter风格)无需修改已有代码。

4.适用环境

  1. 系统需要一组相关产品:如UI主题(所有组件风格一致)、跨平台套件(Windows/Mac按钮+菜单)。

  2. 产品族稳定性高:产品等级结构(如按钮、文本框)不会频繁变更。

  3. 隐藏具体实现:客户端只需关注抽象接口,不关心具体产品的创建细节。

典型场景

  • 跨平台应用:同一功能在不同操作系统下的实现(如Windows/Linux的窗口和按钮)。

  • 游戏风格切换:不同主题的游戏场景(如科幻、中世纪风格的武器和地图)。

5.与工厂方法模式对比

对比维度工厂方法模式抽象工厂模式
核心目标创建单一产品创建一组相关产品(产品族)
工厂职责一个工厂生产一种产品一个工厂生产一族产品
扩展性支持新增产品类型(开闭原则)仅支持新增产品族(倾斜性开闭原则)
  • 工厂方法模式聚焦于 “单一产品的灵活创建”,适合产品类型单一但实现多样的场景,扩展简单。
  • 抽象工厂模式聚焦于 “相关产品族的整体创建”,适合产品之间有依赖关系的场景,能保证产品兼容性,但扩展新的产品类型较复杂。

6.抽象工厂模式的应用实例

说明:抽象工厂模式就像不同品牌的电脑厂商,每个厂商生产一系列配套的电脑部件。

// 抽象产品:CPU
public interface Cpu {void run();
}// 具体产品:Intel CPU
public class IntelCpu implements Cpu {@Overridepublic void run() {System.out.println("Intel CPU 运行中");}
}// 具体产品:AMD CPU
public class AmdCpu implements Cpu {@Overridepublic void run() {System.out.println("AMD CPU 运行中");}
}// 抽象产品:主板
public interface Mainboard {void connect();
}// 具体产品:Intel主板
public class IntelMainboard implements Mainboard {@Overridepublic void connect() {System.out.println("Intel主板 连接组件");}
}// 具体产品:AMD主板
public class AmdMainboard implements Mainboard {@Overridepublic void connect() {System.out.println("AMD主板 连接组件");}
}// 抽象工厂:电脑配件工厂
public interface ComputerFactory {Cpu createCpu();Mainboard createMainboard();
}// 具体工厂:Intel工厂
public class IntelFactory implements ComputerFactory {@Overridepublic Cpu createCpu() {return new IntelCpu();}@Overridepublic Mainboard createMainboard() {return new IntelMainboard();}
}// 具体工厂:AMD工厂
public class AmdFactory implements ComputerFactory {@Overridepublic Cpu createCpu() {return new AmdCpu();}@Overridepublic Mainboard createMainboard() {return new AmdMainboard();}
}// 客户端
public class ComputerClient {public static void main(String[] args) {// 创建Intel工厂,生产Intel系列配件ComputerFactory intelFactory = new IntelFactory();Cpu intelCpu = intelFactory.createCpu();Mainboard intelMainboard = intelFactory.createMainboard();intelCpu.run();          // 输出:Intel CPU 运行中intelMainboard.connect(); // 输出:Intel主板 连接组件// 创建AMD工厂,生产AMD系列配件ComputerFactory amdFactory = new AmdFactory();Cpu amdCpu = amdFactory.createCpu();Mainboard amdMainboard = amdFactory.createMainboard();amdCpu.run();            // 输出:AMD CPU 运行中amdMainboard.connect();   // 输出:AMD主板 连接组件}
}

在这个例子中:

  • 每个品牌工厂(Intel、AMD)生产一系列配套产品(CPU 和主板)
  • 同一工厂生产的产品保证兼容
  • 客户端只需选择品牌工厂,就能获得一套兼容的产品
  • 如果要新增品牌,只需添加新的具体工厂和对应的一系列产品

7.总结

  • 核心思想封装产品族的创建,确保客户端代码与具体产品解耦。

  • 关键设计原则:依赖倒置原则(DIP)、开闭原则(部分支持)。

  • 适用性:适合产品族稳定但需灵活切换主题的场景,但需权衡扩展新产品类型的成本。

通过抽象工厂模式,可以高效管理多组相关对象的创建,尤其适用于需要强一致性主题化的系统设计。

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

相关文章:

  • 关于截屏时实现游戏暂停以及本地和上线不同步问题
  • pycharm2025导入anaconda创建的各个AI环境
  • C++第二十课:快递运费计算器 / 黑白配+石头剪刀布小游戏
  • 医院网络安全重保方案
  • 用 KNN 算法解锁分类的奥秘:从电影类型到鸢尾花开
  • 从电影分类到鸢尾花识别:KNN 算法实战指南
  • @[TOC](计算机是如何⼯作的) JavaEE==网站开发
  • MySQL 关键字总结,并结合 SQL 类型(DDL / DML / DQL / DCL / TCL) 说明每类关键字的作用、使用场景和示例
  • 华为实验综合小练习
  • Android RxJava变换操作符详解
  • MuMu模拟器Pro Mac 安卓手机平板模拟器(Mac中文)
  • 9.对象介绍
  • iOS App TF 上架多工具协作实战,一次高效的应用内测分发流程
  • 【数据结构初阶】--排序(三):冒泡排序、快速排序
  • Tomcat部署JDK8项目启动失败:系统化诊断指南
  • 【科研绘图系列】R语言绘制多种饼图
  • OpenCV 阈值处理
  • 基于定制开发开源AI智能名片与S2B2C商城小程序的H5页面小游戏营销模式创新研究
  • 综合案例:Python 函数知识整合 — 学生成绩管理系统
  • fastdds.ignore_local_endpoints 属性
  • 自动化框架pytest(1)
  • Vue3 Element-plus 封装Select下拉复选框选择器
  • Vue3 + Element Plus 实现可搜索、可折叠、可拖拽的部门树组件
  • 基于element-plus的基础表单样式
  • [微服务]ELK Stack安装与配置全指南
  • Pytest项目_day17(随机测试数据)
  • 大模型微调分布式训练-大模型压缩训练(知识蒸馏)-大模型推理部署(分布式推理与量化部署)-大模型评估测试(OpenCompass)
  • 专题:2025跨境电商市场布局、供应链与产业带赋能报告 |附130+份报告PDF、原数据表汇总下载
  • Sparse-ICP—(3) 点到面稀疏迭代最近点算法(matlab版)
  • PDF Replacer:高效便捷的PDF文档内容替换专家