简单工厂模式详解

简介: 简单工厂模式是一种创建型设计模式,通过工厂类决定实例化哪个具体类,降低客户端与具体类之间的耦合。其特点是封装实例化逻辑,但扩展性较弱,增加新产品需修改工厂类代码。适用于客户端需要创建不同种类的对象但不关心具体实现的场景,如日志处理、图形对象创建和支付系统等。示例代码包括 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;
}


总结

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

目录
相关文章
|
6天前
|
存储 运维 安全
云上金融量化策略回测方案与最佳实践
2024年11月29日,阿里云在上海举办金融量化策略回测Workshop,汇聚多位行业专家,围绕量化投资的最佳实践、数据隐私安全、量化策略回测方案等议题进行深入探讨。活动特别设计了动手实践环节,帮助参会者亲身体验阿里云产品功能,涵盖EHPC量化回测和Argo Workflows量化回测两大主题,旨在提升量化投研效率与安全性。
云上金融量化策略回测方案与最佳实践
|
8天前
|
人工智能 自然语言处理 前端开发
从0开始打造一款APP:前端+搭建本机服务,定制暖冬卫衣先到先得
通义灵码携手科技博主@玺哥超carry 打造全网第一个完整的、面向普通人的自然语言编程教程。完全使用 AI,再配合简单易懂的方法,只要你会打字,就能真正做出一个完整的应用。
8011 19
|
11天前
|
Cloud Native Apache 流计算
资料合集|Flink Forward Asia 2024 上海站
Apache Flink 年度技术盛会聚焦“回顾过去,展望未来”,涵盖流式湖仓、流批一体、Data+AI 等八大核心议题,近百家厂商参与,深入探讨前沿技术发展。小松鼠为大家整理了 FFA 2024 演讲 PPT ,可在线阅读和下载。
4357 10
资料合集|Flink Forward Asia 2024 上海站
|
19天前
|
人工智能 自动驾驶 大数据
预告 | 阿里云邀您参加2024中国生成式AI大会上海站,马上报名
大会以“智能跃进 创造无限”为主题,设置主会场峰会、分会场研讨会及展览区,聚焦大模型、AI Infra等热点议题。阿里云智算集群产品解决方案负责人丛培岩将出席并发表《高性能智算集群设计思考与实践》主题演讲。观众报名现已开放。
|
12天前
|
自然语言处理 数据可视化 API
Qwen系列模型+GraphRAG/LightRAG/Kotaemon从0开始构建中医方剂大模型知识图谱问答
本文详细记录了作者在短时间内尝试构建中医药知识图谱的过程,涵盖了GraphRAG、LightRAG和Kotaemon三种图RAG架构的对比与应用。通过实际操作,作者不仅展示了如何利用这些工具构建知识图谱,还指出了每种工具的优势和局限性。尽管初步构建的知识图谱在数据处理、实体识别和关系抽取等方面存在不足,但为后续的优化和改进提供了宝贵的经验和方向。此外,文章强调了知识图谱构建不仅仅是技术问题,还需要深入整合领域知识和满足用户需求,体现了跨学科合作的重要性。
|
7天前
|
人工智能 容器
三句话开发一个刮刮乐小游戏!暖ta一整个冬天!
本文介绍了如何利用千问开发一款情侣刮刮乐小游戏,通过三步简单指令实现从单个功能到整体框架,再到多端优化的过程,旨在为生活增添乐趣,促进情感交流。在线体验地址已提供,鼓励读者动手尝试,探索编程与AI结合的无限可能。
三句话开发一个刮刮乐小游戏!暖ta一整个冬天!
|
1月前
|
存储 人工智能 弹性计算
阿里云弹性计算_加速计算专场精华概览 | 2024云栖大会回顾
2024年9月19-21日,2024云栖大会在杭州云栖小镇举行,阿里云智能集团资深技术专家、异构计算产品技术负责人王超等多位产品、技术专家,共同带来了题为《AI Infra的前沿技术与应用实践》的专场session。本次专场重点介绍了阿里云AI Infra 产品架构与技术能力,及用户如何使用阿里云灵骏产品进行AI大模型开发、训练和应用。围绕当下大模型训练和推理的技术难点,专家们分享了如何在阿里云上实现稳定、高效、经济的大模型训练,并通过多个客户案例展示了云上大模型训练的显著优势。
104580 10
|
7天前
|
消息中间件 人工智能 运维
12月更文特别场——寻找用云高手,分享云&AI实践
我们寻找你,用云高手,欢迎分享你的真知灼见!
638 39
|
5天前
|
弹性计算 运维 监控
阿里云云服务诊断工具:合作伙伴架构师的深度洞察与优化建议
作为阿里云的合作伙伴架构师,我深入体验了其云服务诊断工具,该工具通过实时监控与历史趋势分析,自动化检查并提供详细的诊断报告,极大提升了运维效率和系统稳定性,特别在处理ECS实例资源不可用等问题时表现突出。此外,它支持预防性维护,帮助识别潜在问题,减少业务中断。尽管如此,仍建议增强诊断效能、扩大云产品覆盖范围、提供自定义诊断选项、加强教育与培训资源、集成第三方工具,以进一步提升用户体验。
626 243
|
1天前
|
弹性计算 运维 监控
云服务测评 | 基于云服务诊断全方位监管云产品
本文介绍了阿里云的云服务诊断功能,包括健康状态和诊断两大核心功能。作者通过个人账号体验了该服务,指出其在监控云资源状态和快速排查异常方面的优势,同时也提出了一些改进建议,如增加告警配置入口和扩大诊断范围等。