简单工厂模式详解

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 简单工厂模式是一种创建型设计模式,通过工厂类决定实例化哪个具体类,降低客户端与具体类之间的耦合。其特点是封装实例化逻辑,但扩展性较弱,增加新产品需修改工厂类代码。适用于客户端需要创建不同种类的对象但不关心具体实现的场景,如日志处理、图形对象创建和支付系统等。示例代码包括 C++ 和 C# 实现。

简单工厂模式详解

定义

简单工厂模式(Simple Factory Pattern)是一种创建型设计模式,用于创建对象的实例。通过一个工厂类来决定实例化哪一个具体类,降低客户端与具体类之间的耦合。

特点

  • 封装实例化逻辑:将对象的创建集中在一个工厂类中。
  • 扩展性较弱:如果需要增加新产品,需要修改工厂类代码,违反开闭原则。

适用场景

  1. 客户端需要创建不同种类的对象,但不需要关心具体的实现。
  2. 需要对实例化的过程进行控制或封装。

使用案例

  1. 日志处理:根据日志类型(如文件日志、数据库日志)创建不同的日志处理器。
  2. 图形对象创建:根据用户选择创建不同的图形对象(如圆形、矩形)。
  3. 支付系统:根据支付方式(如支付宝、微信、银行卡)创建不同的支付对象。

实现代码

C++ 实现

#include <iostream>
#include <string>
#include <memory>

// 产品基类
class Product {
public:
   virtual void use() = 0;
   virtual ~Product() {}
};

// 具体产品 A
class ProductA : public Product {
public:
   void use() override {
       std::cout << "Using Product A" << std::endl;
   }
};

// 具体产品 B
class ProductB : public Product {
public:
   void use() override {
       std::cout << "Using Product B" << std::endl;
   }
};

// 工厂类
class SimpleFactory {
public:
   static std::unique_ptr<Product> createProduct(const std::string& type) {
       if (type == "A") {
           return std::make_unique<ProductA>();
       } else if (type == "B") {
           return std::make_unique<ProductB>();
       } else {
           return nullptr;
       }
   }
};

// 客户端代码
int main() {
   auto product = SimpleFactory::createProduct("A");
   if (product) {
       product->use();
   }
   return 0;
}


C# 实现

using System;

// 产品基类
public abstract class Product {
   public abstract void Use();
}

// 具体产品 A
public class ProductA : Product {
   public override void Use() {
       Console.WriteLine("Using Product A");
   }
}

// 具体产品 B
public class ProductB : Product {
   public override void Use() {
       Console.WriteLine("Using Product B");
   }
}

// 工厂类
public class SimpleFactory {
   public static Product CreateProduct(string type) {
       return type switch {
           "A" => new ProductA(),
           "B" => new ProductB(),
           _ => null
       };
   }
}

// 客户端代码
class Program {
   static void Main(string[] args) {
       Product product = SimpleFactory.CreateProduct("A");
       product?.Use();
   }
}


类图

更多内容

扩展设计模式背景

简单工厂模式是较早被提出的创建型设计模式,虽然不属于 GoF 设计模式,但经常被当作一种基础设计手法,并作为引入工厂方法模式的过渡。以下是一些补充内容:


优点

  1. 职责集中:工厂类集中处理实例化逻辑,简化了客户端代码。
  2. 易于维护:修改实例化逻辑时,只需更改工厂类。
  3. 隐藏实现细节:客户端只需关心工厂接口,无需关心具体产品的实现。

缺点

  1. 扩展性差
  • 每增加一种新产品,都需要修改工厂类的代码。
  • 违反开闭原则(Open/Closed Principle)。
  1. 单一职责问题
  • 工厂类负责太多类型的产品创建,可能变得臃肿。
  1. 不适合复杂场景
  • 当产品之间有复杂的继承或依赖关系时,简单工厂模式的实现变得困难。

如何增强简单工厂模式

  1. 结合单例模式:将工厂类设计为单例,避免频繁创建工厂实例。

public class SimpleFactory {
   private static readonly SimpleFactory instance = new SimpleFactory();
   private SimpleFactory() {}
   public static SimpleFactory Instance => instance;

   public Product CreateProduct(string type) {
       return type switch {
           "A" => new ProductA(),
           "B" => new ProductB(),
           _ => null
       };
   }
}

  1. 结合配置文件或枚举:将产品类型和具体类之间的映射关系配置到文件或用枚举维护,提高灵活性。
  • 示例:通过映射关系动态加载产品:

Dictionary<string, Func<Product>> productMap = new() {
   { "A", () => new ProductA() },
   { "B", () => new ProductB() }
};

public Product CreateProduct(string type) {
   return productMap.TryGetValue(type, out var factory) ? factory() : null;
}

  1. 动态加载类(反射):在需要动态扩展产品时,工厂类可以使用反射加载产品类型:

public Product CreateProduct(string type) {
   Type productType = Type.GetType(type);
   return productType != null ? (Product)Activator.CreateInstance(productType) : null;
}


简单工厂模式与其他模式的比较

特性 简单工厂模式 工厂方法模式 抽象工厂模式
复杂度
扩展性 差(需修改工厂类) 良好(新增工厂子类即可) 非常灵活(支持多个产品族)
适用场景 产品种类少,扩展性要求低的场景 产品种类多但产品结构简单的场景 产品种类多且结构复杂的场景

变体:Parameterized Factory

将产品的创建参数化,可以更灵活地配置对象:

  • 示例

static std::unique_ptr<Product> createProduct(const std::string& type, int config) {
   if (type == "A") {
       return std::make_unique<ProductA>(config);
   } else if (type == "B") {
       return std::make_unique<ProductB>(config);
   }
   return nullptr;
}


实践中的注意事项

  1. 产品不宜过多:如果产品种类繁杂,推荐升级到工厂方法模式或抽象工厂模式。
  2. 避免逻辑臃肿:工厂类的逻辑要简洁,复杂的创建逻辑可以委托给专门的创建类处理。
  3. 性能考虑:动态加载或反射可能影响性能,在高性能场景中需谨慎使用。

示例拓展

将简单工厂与单例模式结合,用于日志系统:

C++ 日志系统

#include <iostream>
#include <string>
#include <memory>

class Logger {
public:
   virtual void log(const std::string& message) = 0;
   virtual ~Logger() {}
};

class FileLogger : public Logger {
public:
   void log(const std::string& message) override {
       std::cout << "File log: " << message << std::endl;
   }
};

class ConsoleLogger : public Logger {
public:
   void log(const std::string& message) override {
       std::cout << "Console log: " << message << std::endl;
   }
};

class LoggerFactory {
public:
   static std::unique_ptr<Logger> getLogger(const std::string& type) {
       if (type == "file") {
           return std::make_unique<FileLogger>();
       } else if (type == "console") {
           return std::make_unique<ConsoleLogger>();
       }
       return nullptr;
   }
};

int main() {
   auto logger = LoggerFactory::getLogger("console");
   if (logger) {
       logger->log("Hello, world!");
   }
   return 0;
}


总结

简单工厂模式是一种结构简单但实用的设计模式,适合用于需求变化不频繁的小型项目或模块中,更多内容完善了简单工厂模式的局限性及改进方案,并扩展了实际应用案例,展示了模式的灵活性和变体的实现方法。但在扩展性要求高的场景中,推荐使用工厂方法模式或抽象工厂模式以增强灵活性。

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
打赏
0
3
3
0
18
分享
相关文章
UML中类图的介绍与使用
类图是 UML 中用于展示系统静态结构的重要工具,包括类、接口及其关系。类图有助于系统可视化、团队沟通、发现设计问题、文档化系统和辅助开发工具。类图的三大元素是类、接口和关系,其中关系又细分为关联、聚合、组合、继承、实现和依赖。类图在设计模式学习和实际开发中非常重要,许多现代 IDE 都支持从类图生成代码或从代码生成类图。
366 2
|
7月前
|
第四问:QT中信号和槽原理
Qt的信号与槽机制是观察者模式的典型实现,允许对象间通信而不直接依赖。信号用于通知事件发生,槽是响应信号的函数,通过`QObject::connect()`连接。这种机制实现了松耦合、灵活扩展和自动通知,适用于UI更新和数据绑定等场景。
189 1
|
7月前
|
适配器模式(Adapter Pattern)
适配器模式是一种结构型设计模式,通过将一个类的接口转换为客户期望的另一个接口,使原本接口不兼容的类可以一起工作。它包括目标接口、适配者和适配器三个核心角色。适配器模式常用于解决旧系统兼容性问题、第三方库整合和统一接口等场景。该模式有类适配器和对象适配器两种实现方式,分别通过继承和组合实现。适配器模式的优点包括提高兼容性、遵循开闭原则和灵活性高,但也存在适配器数量增加导致复杂性和可能影响性能的缺点。
253 1
第五问:一个程序从点击到启动发生了什么?
一个可执行程序从用户点击启动到运行,经历了8个主要阶段:用户触发启动、操作系统查找文件、进程创建、可执行文件加载到内存、初始化程序上下文、执行程序入口点、程序运行和程序退出。涉及硬盘、内存、缓存等硬件交互。
148 0
单例模式详解
单例模式是一种常用的创建型设计模式,确保某个类只有一个实例,并提供一个全局访问点。本文详细介绍了单例模式的定义、特点、适用场景、优缺点及实现代码(C++ 和 C#),并探讨了线程安全的实现细节和与依赖注入的结合使用。
148 0
设计模式概述
设计模式是软件工程中的最佳实践,帮助开发者解决常见问题,提高代码的可重用性、可读性和可靠性。学习设计模式可以提升思维能力、标准化程序设计、增强代码质量。文章介绍了设计模式的分类(创建型、结构型、行为型)及其在流行框架中的应用,建议读者掌握SOLID原则并深入学习GoF的23种设计模式。
132 3
设计模式概述
|
7月前
|
工厂方法模式
工厂方法模式是一种创建型设计模式,定义一个创建对象的接口,但让子类决定具体实例化哪个类。该模式具有高内聚、低耦合的特点,支持动态扩展新产品类型,适用于复杂或经常变化的产品族。其主要组成部分包括抽象产品、具体产品、抽象工厂和具体工厂。工厂方法模式遵循开闭原则,新增产品无需修改现有代码,但会增加系统复杂性。
73 5
第六问:http和https区别与联系
HTTP 和 HTTPS 是现代网络通信中的两种重要协议。HTTP 是明文传输协议,无加密功能;HTTPS 在 HTTP 基础上加入 SSL/TLS 加密层,提供数据加密、身份验证和数据完整性保障。HTTP 适用于非敏感信息传输,如新闻网站;HTTPS 适用于在线支付、账户登录等需要保护用户数据的场景。
195 0
抽象工厂模式
抽象工厂模式是一种创建型设计模式,提供接口用于创建一系列相关或依赖的对象,无需指定具体类。适用于产品族的创建,确保兼容性和一致性。优点包括分离接口与实现、产品族一致性、遵循开闭原则;缺点是扩展产品种类困难、增加系统复杂性。常见应用场景包括跨平台 UI、数据库访问、游戏开发和主题风格切换。
85 0
django面试题(21道)
1、什么是wsgi? WSGI是Python在处理HTTP请求时,规定的一种处理方式。如一个HTTP Request过来了,那么就有一个相应的处理函数来进行处理和返回结果。
7527 0
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等