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

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

maynowei9个月前 (09-29)技术知识118


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

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


记忆口诀:

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

相关文章

分析 Rust 程序的火焰图(rust火吗)

分析 Rust 程序的火焰图(Flame Graph)是定位性能瓶颈的核心手段,其核心是通过可视化的函数调用栈和时间分布,找到 CPU 耗时、内存分配、锁竞争等热点。以下是详细的分析方法和步骤,结合...

C++26中同步与原子操作新变化(c++ 同步)

引言随着多核处理器和并发编程的普及,C++26进一步增强了对同步与原子操作的支持,为开发者提供了更高效、更安全的工具来应对多线程编程中的数据竞争与同步挑战。自C++11引入原子操作以来,C++标准库在...

什么?Java 中的锁还有状态?(java中的锁都有哪些类型)

线程如果锁住了某个资源,致使其他线程无法访问的这种锁被称为悲观锁,相反,线程不锁住资源的锁被称为乐观锁,而自旋锁是基于 CAS 机制实现的,CAS又是乐观锁的一种实现,那么对于锁来说,多个线程同步访问...

Oracle中泄露“天机”的TNS(在oracle中发出的下列查询)

数据库的安全是长期存在的问题。在目前大量的数据泄露事件以及漏洞面前,大家看到的大都是SQl注入、越权操作、缓冲区溢出等这些具体漏洞。往往却忽视了造成这些问题的前提,黑客想要入侵数据库一定会尝试获取数据...

Oracle工具PLSQL登录时提示初始化失败,无法锁定OCI.dll错误解决

报错信息: (没有登录)-PL/SQL Developer Initialization error 无法锁定OCI dll OracleHomeKey: OracleHomeDir:E\instan...

Java集合框架:总结(java集合框架是什么?说出一些集合框架的优点)

Java集合框架这个系列做了一个整理,主要包括:Map系:HashMap, LinkedHashMap, TreeMap, WeakHashMap, EnumMap;List系:ArrayList,...