设计模式之-简单工厂_简单工厂模式是什么
一、【概念定义】—— “封装对象创建逻辑,一个入口管所有”
简单工厂(Simple Factory):
一种“创建封装型”创建型设计模式(注意:不是GoF 23种经典模式,但极其常用!),它提供一个静态方法,根据参数决定创建并返回哪个具体类的实例。
核心思想:将对象的创建逻辑集中到一个工厂类中,客户端只与工厂交互,不直接 new 对象。
目标:简化客户端代码,集中管理对象创建,便于扩展和维护。
口诀:“对象创建别手搓,简单工厂来负责;传入类型给工厂,对象到手不用愁!”
二、【解决的问题】—— “创建散乱地狱”的三大灾难
想象你正在开发一个图形绘制系统:
- 创建散落:
- java
- 深色版本
- // 在A模块 Shape s1 = new Circle(); // 在B模块 Shape s2 = new Rectangle(); // 在C模块 if (config == "circle") s3 = new Circle();
- → 创建逻辑重复!新增图形?所有模块都要找出来改!
- 简单工厂:
- ShapeFactory.createShape("circle") → 返回 Circle 实例;
- ShapeFactory.createShape("rectangle") → 返回 Rectangle 实例;
→ 客户端统一调用工厂!新增“Triangle”?只需改工厂类!
核心解决:
对象创建散乱 → 集中到工厂类;扩展困难 → 新增产品只需修改工厂;客户端耦合具体类 → 客户端只依赖抽象(Shape)和工厂。
三、【适用场景】— “集中创建对象”的四大名器
你该用简单工厂,如果符合以下“四简原则”:
场景 | 描述 | 举例 |
对象创建逻辑简单 | 创建过程不复杂,无多步构建 | 图形对象、日志记录器、数据库连接(简单版) |
产品类型较少 | 具体类数量不多(≤5个),且相对稳定 | 支付方式(支付宝、微信)、文件格式读取器(JSON、XML) |
客户端需统一入口 | 希望所有对象通过一个工厂获取 | 配置加载器、缓存实例获取、简单插件系统 |
快速原型开发 | 需要快速实现,不追求极致扩展性 | 小型项目、Demo、教学示例 |
警告:如果产品类型多、变化频繁、创建过程复杂 —— 请用 工厂方法 或 抽象工厂!
四、【经典案例】—— 四大“快捷服务台”的成名战
1. 【图形绘制系统】—— 圆、矩、三角,一键创建!
需要创建不同图形进行绘制
各处 new Circle(), new Rectangle() → 散乱难维护;
简单工厂:ShapeFactory.createShape("circle") → 返回 Circle;ShapeFactory.createShape("triangle") → 返回 Triangle;
效果:新增“五角星”?只需在工厂中加 case "star"!所有绘制模块零修改!
2. 【支付方式工厂】—— 支付宝、微信、银联,统一入口!
客户端需要根据用户选择创建支付对象
if (payType == "alipay") pay = new Alipay(); → 重复代码;
简单工厂:
PaymentFactory.createPayment("alipay") → 返回 Alipay;
PaymentFactory.createPayment("wechat") → 返回 WechatPay;
效果:新增“Apple Pay”?只需改工厂!支付入口统一管理!
3. 【文件读取器】—— JSON、XML、CSV,按格式创建!
需要根据文件后缀创建对应解析器
各处判断后缀并 new JsonReader() → 逻辑重复;
简单工厂:
FileReaderFactory.createReader(".json") → 返回 JsonReader;
FileReaderFactory.createReader(".xml") → 返回 XmlReader;
效果:新增“YAML支持”?只需工厂加 case ".yaml"!解析器创建集中控制!
4. 【日志记录器】—— 控制台、文件、网络,按需创建!
需要根据配置创建不同日志输出器
if (config == "file") logger = new FileLogger(); → 配置变更需改多处;
简单工厂:
LoggerFactory.createLogger("console") → 返回 ConsoleLogger;
LoggerFactory.createLogger("file") → 返回 FileLogger;
效果:新增“数据库日志”?只需工厂加 case "db"!日志系统灵活切换!
五、【结构简述】—— 简单工厂宇宙的“三位一体”
简单工厂三要素:
角色 | 职责 | 比喻 |
Product(产品接口/抽象类) | 定义产品的公共接口 | “图形协议” —— 声明 draw() 方法 |
ConcreteProduct(具体产品) | 实现 Product 接口的具体类 | “圆形”、“矩形” —— 每个图形知道如何绘制自己 |
SimpleFactory(简单工厂) | 静态方法,根据参数创建并返回具体产品实例 | “图形服务台” —— 接收 "circle" 返回 Circle 对象 |
调用流程:
Client → 调用
SimpleFactory.createProduct(type) → 工厂内部 new ConcreteProduct() → 返回 Product 引用
关键:工厂类通常是静态方法,无状态!客户端不关心具体类名!
六、【注意事项】—— “快捷”虽好,小心“工厂臃肿”!
1. 违反开闭原则
新增产品必须修改工厂类 → 违反“对扩展开放,对修改关闭”!
权衡:产品类型稳定或变化少时使用;频繁变化 → 用工厂方法模式!
2. 工厂类职责过重
所有产品创建逻辑挤在一个工厂 → 类膨胀!
解决:按业务拆分多个简单工厂(如 ShapeFactory, PaymentFactory);产品多时 → 升级为工厂方法模式。
3. 无法应对复杂创建
如果创建过程复杂(如需多步初始化、依赖注入)→ 简单工厂力不从心!
升级方案:用生成器模式(Builder)或依赖注入框架(如Spring)。
4. 简单工厂 vs 工厂方法
简单工厂:一个工厂类,用条件语句创建所有产品 → 集中式管理;工厂方法:每个产品一个工厂子类,通过多态创建 → 符合开闭原则;
选择:快速开发、产品少 → 简单工厂;产品多、需扩展 → 工厂方法。
七、【实战应用】—— 30行代码,打造“图形简单工厂系统”
java深色版本
// 1. 产品接口:图形
interface Shape {
void draw();
}
// 2. 具体产品:圆形
class Circle implements Shape {
@Override
public void draw() {
System.out.println(" 绘制一个圆形");
}
}
// 3. 具体产品:矩形
class Rectangle implements Shape {
@Override
public void draw() {
System.out.println(" 绘制一个矩形");
}
}
// 4. 具体产品:三角形
class Triangle implements Shape {
@Override
public void draw() {
System.out.println(" 绘制一个三角形");
}
}
// 5. 简单工厂:图形工厂(静态方法)
class ShapeFactory {
public static Shape createShape(String type) {
switch (type.toLowerCase()) {
case "circle":
return new Circle();
case "rectangle":
return new Rectangle();
case "triangle":
return new Triangle();
default:
throw new IllegalArgumentException(" 未知图形类型: " + type);
}
}
}
// 6. 客户端
public class SimpleFactoryDemo {
public static void main(String[] args) {
System.out.println(" 图形工厂启动...");
// 客户端只需调用工厂,无需关心具体类!
Shape circle = ShapeFactory.createShape("circle");
Shape rectangle = ShapeFactory.createShape("rectangle");
Shape triangle = ShapeFactory.createShape("triangle");
circle.draw();
rectangle.draw();
triangle.draw();
// 新增“五角星”?只需:
// 1. 创建 Star 类实现 Shape;
// 2. 在 ShapeFactory 中添加 case "star";
// 3. 客户端调用 ShapeFactory.createShape("star")!
// —— 客户端代码无需修改!
}
}运行结果:
深色版本 图形工厂启动...
绘制一个圆形
绘制一个矩形
绘制一个三角形看到了吗?客户端完全不知道 Circle、Rectangle 类名!
ShapeFactory.createShape("circle") → 返回 Circle 实例;ShapeFactory.createShape("triangle") → 返回 Triangle 实例;
新增“五角星图形”?只需两步:
class Star implements Shape { public void draw() { System.out.println(" 绘制一个五角星"); } }
// 在 ShapeFactory 中添加: case "star": return new Star();
—— 所有使用图形的地方自动支持新图形!这就是简单工厂的便捷!
最后总结:简单工厂 —— 对象界的“快捷服务台”
以前:new 对象满天飞 → 创建散乱,扩展痛苦;
现在:工厂统一管理 → 一个入口,集中控制!
简单工厂就是对象界的“万能服务台” —— 用一个静态方法封装创建逻辑,让客户端告别 new,拥抱简洁!
记忆口诀:
对象创建莫手搓,
简单工厂来负责。
传入类型给工厂,
对象到手不用愁!
图形支付日志器,
快捷创建它最牛。
产品稳定变化少,
工厂方法不强求!
莫当经典模式用,
实用至上是王道!