工厂方法模式

简介: 工厂方法模式是一种创建型设计模式,定义一个创建对象的接口,但让子类决定具体实例化哪个类。该模式具有高内聚、低耦合的特点,支持动态扩展新产品类型,适用于复杂或经常变化的产品族。其主要组成部分包括抽象产品、具体产品、抽象工厂和具体工厂。工厂方法模式遵循开闭原则,新增产品无需修改现有代码,但会增加系统复杂性。

工厂方法模式详解

定义

工厂方法模式(Factory Method Pattern)是一种创建型设计模式,定义一个创建对象的接口,但让子类决定要实例化的具体类。通过这种方式,工厂方法模式将对象的实例化推迟到子类。

特点

  1. 解耦性:客户端通过工厂方法创建对象,而无需关心具体的类名。
  2. 扩展性:可以通过新增具体工厂类来扩展新产品类型,符合开闭原则。
  3. 灵活性:支持产品族的扩展。

使用场景

  1. 当具体类的创建复杂时:需要将创建逻辑封装到子类中。
  2. 客户代码需要依赖抽象类或接口:而不是具体实现。
  3. 产品种类经常变化:需要动态扩展新的产品类。

工厂方法模式的结构

工厂方法模式由以下几个部分组成:

  1. 抽象产品(Product):定义产品的接口。
  2. 具体产品(ConcreteProduct):实现产品接口。
  3. 抽象工厂(Creator):定义工厂方法。
  4. 具体工厂(ConcreteCreator):实现工厂方法,负责创建具体产品。

实现代码

C++ 实现

#include <iostream>
#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 Factory {
public:
   virtual std::unique_ptr<Product> createProduct() = 0;
   virtual ~Factory() {}
};

// 具体工厂 A
class FactoryA : public Factory {
public:
   std::unique_ptr<Product> createProduct() override {
       return std::make_unique<ProductA>();
   }
};

// 具体工厂 B
class FactoryB : public Factory {
public:
   std::unique_ptr<Product> createProduct() override {
       return std::make_unique<ProductB>();
   }
};

// 客户端代码
int main() {
   std::unique_ptr<Factory> factory = std::make_unique<FactoryA>();
   auto product = factory->createProduct();
   product->use();

   factory = std::make_unique<FactoryB>();
   product = factory->createProduct();
   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 abstract class Factory {
   public abstract Product CreateProduct();
}

// 具体工厂 A
public class FactoryA : Factory {
   public override Product CreateProduct() {
       return new ProductA();
   }
}

// 具体工厂 B
public class FactoryB : Factory {
   public override Product CreateProduct() {
       return new ProductB();
   }
}

// 客户端代码
class Program {
   static void Main(string[] args) {
       Factory factory = new FactoryA();
       Product product = factory.CreateProduct();
       product.Use();

       factory = new FactoryB();
       product = factory.CreateProduct();
       product.Use();
   }
}

类图

优缺点

优点

  1. 遵循开闭原则:新增产品无需修改已有代码,只需新增具体工厂类。
  2. 高内聚、低耦合:通过工厂方法隔离了具体产品与客户端的依赖。
  3. 灵活性:可以动态决定实例化的具体类。

缺点

  1. 增加复杂性:每新增一个产品类,都需要新增一个对应的工厂类。
  2. 过度设计:当产品种类固定时,工厂方法模式可能显得繁琐。

工厂方法模式的变体与扩展

  1. 参数化工厂:通过传递参数决定创建哪种产品,减少具体工厂类的数量。
  • 示例

public class ParameterizedFactory : Factory {
   public override Product CreateProduct(string type) {
       return type switch {
           "A" => new ProductA(),
           "B" => new ProductB(),
           _ => throw new ArgumentException("Invalid type")
       };
   }
}

  1. 结合简单工厂:将简单工厂作为抽象工厂的默认实现,用于处理常见或不复杂的实例化逻辑。
  2. 与依赖注入结合:通过 DI 容器动态注入具体工厂,简化复杂产品族的管理。

总结

  1. 工厂方法模式提供了更高的扩展性和灵活性,适合复杂或动态变化的产品族。
  2. 它的实现复杂度较高,不适合产品种类固定或单一的场景。
  3. 在实际项目中,工厂方法模式常与依赖注入、简单工厂、抽象工厂模式结合使用,以实现更加灵活的设计架构。
目录
相关文章
|
存储 安全 编译器
【Qt 底层机制之信号和槽 】深入探究Qt信号和槽背后的原理
【Qt 底层机制之信号和槽 】深入探究Qt信号和槽背后的原理
3223 4
|
10月前
|
设计模式 安全 C#
单例模式详解
单例模式是一种常用的创建型设计模式,确保某个类只有一个实例,并提供一个全局访问点。本文详细介绍了单例模式的定义、特点、适用场景、优缺点及实现代码(C++ 和 C#),并探讨了线程安全的实现细节和与依赖注入的结合使用。
338 0
|
11月前
|
消息中间件 存储 缓存
大厂面试高频:Kafka 工作原理 ( 详细图解 )
本文详细解析了 Kafka 的核心架构和实现原理,消息中间件是亿级互联网架构的基石,大厂面试高频,非常重要,建议收藏。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:Kafka 工作原理 ( 详细图解 )
|
6月前
|
传感器 自然语言处理 监控
快速部署实现Bolt.diy
Bolt.diy 是 Bolt.new 的开源版本,提供灵活的自然语言交互与全栈开发支持。基于阿里云函数计算 FC 和百炼模型服务,最快5分钟完成部署。新手注册阿里云账号后可领取免费额度,按指引开通相关服务并授权。通过项目模板一键部署,配置 API-KEY 后即可使用。Bolt.diy 支持多种场景,如物联网原型开发、久坐提醒、语音控制灯光等,助力快速实现创意应用。
2404 22
|
10月前
|
安全 编译器 C++
constexpr、const和 #define 的比较
本文比较了 `constexpr`、`const` 和 `#define` 在 C++ 中定义常量和函数的优缺点。`constexpr` 用于编译期求值,提供更高的性能和类型安全性;`const` 保证变量在运行期间不可修改,增强代码可靠性;`#define` 用于宏定义,适用于简单的常量和跨平台兼容性。选择时应根据具体需求和代码上下文决定。
296 0
|
10月前
|
存储 设计模式 算法
命令模式(Command Pattern)
命令模式是一种行为型设计模式,将请求封装为对象,实现参数化请求、支持撤销操作和记录日志。适用于需要解耦发送者和接收者的场景,如智能家居系统中的遥控器控制电灯开关并支持撤销功能。优点包括解耦、支持撤销与恢复操作,但过度使用会增加系统复杂度。
168 7
|
10月前
|
JavaScript 前端开发 Java
JS中的隐式类型转换规则
JavaScript 是一门弱类型语言,变量类型在运行时会进行隐式转换。本文总结了常见的隐式转换规则,包括运算符转换、等号比较和布尔值转换等。例如,`1 + {a: 1}` 会先调用对象的 `toString()` 方法,最终结果为 `&#39;1[object Object]&#39;`。此外,还详细解析了 `undefined` 和 `null` 的运算行为,以及 `![] == []` 等特殊情况。通过这些例子,帮助开发者更好地理解 JavaScript 中的类型转换机制。
170 6
JS中的隐式类型转换规则
|
12月前
|
前端开发 JavaScript 算法
使用 JavaScript 数组方法实现排序与去重
【10月更文挑战第21天】通过灵活运用 `sort()` 方法和 `filter()` 方法,我们可以方便地实现数组的排序和去重。同时,深入理解排序和去重的原理,以及根据实际需求进行适当的优化,能够更好地应对不同的情况。可以通过实际的项目实践来进一步掌握这些技巧,并探索更多的应用可能性。
332 59
|
10月前
|
设计模式 IDE 数据可视化
UML中类图的介绍与使用
类图是 UML 中用于展示系统静态结构的重要工具,包括类、接口及其关系。类图有助于系统可视化、团队沟通、发现设计问题、文档化系统和辅助开发工具。类图的三大元素是类、接口和关系,其中关系又细分为关联、聚合、组合、继承、实现和依赖。类图在设计模式学习和实际开发中非常重要,许多现代 IDE 都支持从类图生成代码或从代码生成类图。
490 2
|
10月前
|
设计模式 C# C++
适配器模式(Adapter Pattern)
适配器模式是一种结构型设计模式,通过将一个类的接口转换为客户期望的另一个接口,使原本接口不兼容的类可以一起工作。它包括目标接口、适配者和适配器三个核心角色。适配器模式常用于解决旧系统兼容性问题、第三方库整合和统一接口等场景。该模式有类适配器和对象适配器两种实现方式,分别通过继承和组合实现。适配器模式的优点包括提高兼容性、遵循开闭原则和灵活性高,但也存在适配器数量增加导致复杂性和可能影响性能的缺点。
349 1
下一篇
oss教程