当前位置:首页 > 技术知识 > 正文内容

设计模式之-简单工厂_简单工厂模式是什么

maynowei5个月前 (09-29)技术知识67


一、【概念定义】—— “封装对象创建逻辑,一个入口管所有”

简单工厂(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,拥抱简洁!


记忆口诀:

对象创建莫手搓,
简单工厂来负责。
传入类型给工厂,
对象到手不用愁!
图形支付日志器,
快捷创建它最牛。
产品稳定变化少,
工厂方法不强求!
莫当经典模式用,
实用至上是王道!

相关文章

在手机上演示axure原型(怎么在axure中画出手机原型)

AXSHARE APP发布啦,以后大家的原型可以通过这款APP进行预览演示咯。小编迫不及待的体验了一下这款APP。要使用这款APP,首先需要有axshare的账号。账号注册地址:https://sha...

Objective C interface(objective什么意思)

在Objective C里面,interface基本可以理解为其他语言里面的class。当然也有些不同。首先我们可以新建一个Objective-C的file。这里我们添加一个MyClass.m和一个M...

C# 中的多线程同步机制:lock、Monitor 和 Mutex 用法详解

在多线程编程中,线程同步是确保多个线程安全地访问共享资源的关键技术。C# 提供了几种常用的同步机制,其中 lock、Monitor 和 Mutex 是最常用的同步工具。本文将全面介绍这三种同步机制的用...

C语言进阶教程:线程同步:互斥锁、条件变量与信号量

在多线程编程中,线程同步是确保数据一致性和程序正确性的关键。当多个线程需要访问共享资源时,如果缺乏适当的同步机制,就可能导致竞态条件(Race Condition)、死锁(Deadlock)等问题。本...

c++ 继承简介(c++继承的概念)

24.1 — 继承简介2024 年 6 月 5 日在上一章中,我们讨论了对象组合,即从更简单的类和类型构建复杂类。对象组合非常适合构建与其部分具有“has-a”关系的新对象。但是,对象组合只是 C++...

一个快要被忘记的数据库开发岗位,但应该被尊重

数据库测试,似乎是被人遗忘的数据库职业,但依然是不错的选择。底下是我在某站找的招聘启事,就连蚂蚁金服都在积极寻找数据库测试人:要说我经历的项目,大大小小也有几十个,从 C/S, B/S, 再到 B/C...