设计模式-2--工厂模式(Factory Pattern)

2023-11-19

一、 什么是工厂模式

工厂模式(Factory Pattern)是一种创建型设计模式,它提供了一种创建对象的接口,但是将对象的实例化过程推迟到子类中。工厂模式允许通过调用一个共同的接口方法来创建不同类型的对象,而无需暴露对象的实例化逻辑。

工厂模式的主要目标是解耦对象的创建和使用,以及提供一种更灵活的方式来管理对象的实例化。通过使用工厂模式,可以轻松添加新类型的对象,而不会影响到已有的代码。

工厂模式通常涉及以下几个核心角色:

  1. 产品(Product):这是一个抽象类或接口,定义了所创建对象的通用接口。
  2. 具体产品(Concrete Product):这些是实现了产品接口的具体类,它们是工厂方法模式的创建目标。
  3. 工厂(Factory):这是一个抽象类或接口,定义了创建对象的接口方法。工厂类通常是一个创建具体产品对象的工厂方法。
  4. 具体工厂(Concrete Factory):这些是实现了工厂接口的具体类,它们负责实例化具体的产品对象。

工厂模式可以分为三种常见的变体:

  1. 简单工厂模式(Simple Factory Pattern):通过一个共同的工厂类来创建对象,客户端只需传递一个参数来指定所需的对象类型。虽然不是严格意义上的设计模式,但它是工厂模式的基础。
  2. 工厂方法模式(Factory Method Pattern):定义一个工厂接口,具体的工厂子类负责实现工厂接口并创建对象。每个具体工厂对应一个特定的产品。
  3. 抽象工厂模式(Abstract Factory Pattern):提供了一种创建一系列相关或相互依赖对象的接口,而无需指定具体类。适用于创建一组相互关联的产品。

二、简单工厂模式的代码样例

简单工厂模式(Simple Factory Pattern)虽然不是严格的设计模式,但它是工厂模式的一种基本形式,适用于创建单一类别的对象。在简单工厂模式中,有一个工厂类负责根据客户端的请求创建不同类型的对象。

以下是一个用C++实现简单工厂模式的示例:

#include <iostream>

// 抽象产品类
class Product {
public:
    virtual void operation() = 0;
};

// 具体产品类A
class ConcreteProductA : public Product {
public:
    void operation() override {
        std::cout << "ConcreteProductA operation." << std::endl;
    }
};

// 具体产品类B
class ConcreteProductB : public Product {
public:
    void operation() override {
        std::cout << "ConcreteProductB operation." << std::endl;
    }
};

// 简单工厂类
class SimpleFactory {
public:
    // 根据传入的参数创建不同类型的产品对象
    static Product* createProduct(char type) {
        if (type == 'A') {
            return new ConcreteProductA();
        } else if (type == 'B') {
            return new ConcreteProductB();
        } else {
            return nullptr; // 可以抛出异常或其他处理
        }
    }
};

int main() {
    // 客户端通过工厂创建产品
    Product* productA = SimpleFactory::createProduct('A');
    Product* productB = SimpleFactory::createProduct('B');

    if (productA) {
        productA->operation();
        delete productA;
    }

    if (productB) {
        productB->operation();
        delete productB;
    }

    return 0;
}

在这个例子中,我们定义了一个抽象产品类 Product,然后有两个具体的产品类 ConcreteProductA 和 ConcreteProductB。简单工厂类 SimpleFactory 有一个静态方法 createProduct,根据传入的参数来创建不同类型的产品对象。

虽然简单工厂模式简化了对象的实例化,但它的弊端在于如果需要添加新类型的产品,就需要修改工厂类的代码。因此,当需要支持更多产品类型时,更推荐使用工厂方法模式或抽象工厂模式。

三、工厂方法模式的代码样例

工厂方法模式(Factory Method Pattern)是一种创建型设计模式,它定义了一个用于创建对象的接口,但是将具体的对象实例化推迟到子类中。每个具体的工厂子类负责创建特定类型的对象。这种模式使得客户端代码与具体创建对象的代码分离,实现了松耦合。

以下是一个用C++实现工厂方法模式的示例:

#include <iostream>

// 抽象产品类
class Product {
public:
    virtual void operation() = 0;
};

// 具体产品类A
class ConcreteProductA : public Product {
public:
    void operation() override {
        std::cout << "ConcreteProductA operation." << std::endl;
    }
};

// 具体产品类B
class ConcreteProductB : public Product {
public:
    void operation() override {
        std::cout << "ConcreteProductB operation." << std::endl;
    }
};

// 抽象工厂类
class Factory {
public:
    virtual Product* createProduct() = 0;
};

// 具体工厂类A
class ConcreteFactoryA : public Factory {
public:
    Product* createProduct() override {
        return new ConcreteProductA();
    }
};

// 具体工厂类B
class ConcreteFactoryB : public Factory {
public:
    Product* createProduct() override {
        return new ConcreteProductB();
    }
};

int main() {
    // 客户端通过具体工厂来创建产品
    Factory* factoryA = new ConcreteFactoryA();
    Product* productA = factoryA->createProduct();
    productA->operation();
    delete factoryA;
    delete productA;

    Factory* factoryB = new ConcreteFactoryB();
    Product* productB = factoryB->createProduct();
    productB->operation();
    delete factoryB;
    delete productB;

    return 0;
}

在这个例子中,我们定义了一个抽象产品类 Product,然后有两个具体的产品类 ConcreteProductA 和 ConcreteProductB。抽象工厂类 Factory 定义了一个纯虚函数 createProduct,由具体的工厂子类来实现该方法并创建特定类型的产品对象。

客户端使用具体的工厂类来创建产品,这样客户端代码与具体的产品创建代码分离,实现了解耦。工厂方法模式允许通过添加新的工厂子类来支持新的产品类型,而无需修改现有的代码。

四、抽象工厂模式的代码样例

抽象工厂模式(Abstract Factory Pattern)是一种创建型设计模式,它提供一个接口用于创建一系列相关或相互依赖的对象,而无需指定具体类。抽象工厂模式适用于需要创建一组相互关联的产品的情况,它将一组相关的工厂类封装起来。

以下是一个用C++实现抽象工厂模式的示例:

#include <iostream>

// 抽象产品类A
class AbstractProductA {
public:
    virtual void operationA() = 0;
};

// 具体产品类A1
class ConcreteProductA1 : public AbstractProductA {
public:
    void operationA() override {
        std::cout << "ConcreteProductA1 operation." << std::endl;
    }
};

// 具体产品类A2
class ConcreteProductA2 : public AbstractProductA {
public:
    void operationA() override {
        std::cout << "ConcreteProductA2 operation." << std::endl;
    }
};

// 抽象产品类B
class AbstractProductB {
public:
    virtual void operationB() = 0;
};

// 具体产品类B1
class ConcreteProductB1 : public AbstractProductB {
public:
    void operationB() override {
        std::cout << "ConcreteProductB1 operation." << std::endl;
    }
};

// 具体产品类B2
class ConcreteProductB2 : public AbstractProductB {
public:
    void operationB() override {
        std::cout << "ConcreteProductB2 operation." << std::endl;
    }
};

// 抽象工厂类
class AbstractFactory {
public:
    virtual AbstractProductA* createProductA() = 0;
    virtual AbstractProductB* createProductB() = 0;
};

// 具体工厂类1
class ConcreteFactory1 : public AbstractFactory {
public:
    AbstractProductA* createProductA() override {
        return new ConcreteProductA1();
    }
    AbstractProductB* createProductB() override {
        return new ConcreteProductB1();
    }
};

// 具体工厂类2
class ConcreteFactory2 : public AbstractFactory {
public:
    AbstractProductA* createProductA() override {
        return new ConcreteProductA2();
    }
    AbstractProductB* createProductB() override {
        return new ConcreteProductB2();
    }
};

int main() {
    // 客户端通过具体工厂来创建一组相关的产品
    AbstractFactory* factory1 = new ConcreteFactory1();
    AbstractProductA* productA1 = factory1->createProductA();
    AbstractProductB* productB1 = factory1->createProductB();
    productA1->operationA();
    productB1->operationB();
    delete factory1;
    delete productA1;
    delete productB1;

    AbstractFactory* factory2 = new ConcreteFactory2();
    AbstractProductA* productA2 = factory2->createProductA();
    AbstractProductB* productB2 = factory2->createProductB();
    productA2->operationA();
    productB2->operationB();
    delete factory2;
    delete productA2;
    delete productB2;

    return 0;
}

在这个例子中,我们定义了两组相关的产品类:AbstractProductA 和 AbstractProductB,然后分别有两个具体的产品类。抽象工厂类 AbstractFactory 定义了两个纯虚函数,分别用于创建 AbstractProductA 和 AbstractProductB 对象。具体的工厂类 ConcreteFactory1 和 ConcreteFactory2 实现了这些方法,并创建特定类型的产品对象。

通过使用抽象工厂模式,客户端可以通过具体的工厂来创建一组相关的产品,实现了一种创建一系列相互关联产品的方式。这有助于实现高内聚、低耦合的设计。

五、三种工厂模式之间的关系

这三种工厂模式(简单工厂模式、工厂方法模式和抽象工厂模式)都是创建型设计模式,旨在解决对象的创建问题。它们之间有一些共同点,但也存在一些差异。下面是它们之间的关系和区别:

共同点:

  • 都关注对象的创建,封装了对象的实例化过程,使客户端代码与具体创建逻辑分离。
  • 都遵循了开闭原则,即可以通过添加新的产品类或工厂类来扩展功能,而无需修改现有代码。

差异:

  • 简单工厂模式:虽然不是严格意义上的设计模式,但它是工厂模式的基础。它通过一个共同的工厂类来创建不同类型的对象,客户端根据参数来指定对象类型。适用于创建单一类别的对象。
  • 工厂方法模式:定义了一个工厂接口,由具体的工厂子类来实现工厂接口并创建特定类型的产品对象。每个工厂只负责创建一种产品。适用于创建一组相关的产品,每个产品有一个对应的工厂。
  • 抽象工厂模式:提供了一种创建一组相关或相互依赖对象的接口,每个具体的工厂子类负责创建一组相关产品。适用于创建一组相互关联的产品,每组产品都有一个对应的工厂。

适用场景:

  • 简单工厂模式适用于创建简单的对象,例如基于传入参数创建对象的情况。
  • 工厂方法模式适用于需要创建多种具有相同接口的产品,而且每种产品都有对应的工厂。
  • 抽象工厂模式适用于创建一组相关或相互依赖的产品,且每组产品都有对应的工厂。

总之,这三种工厂模式都在不同情况下提供了灵活的对象创建机制,可以根据具体的需求来选择合适的模式。简单工厂模式通常是基础,而工厂方法模式和抽象工厂模式则在更复杂的场景下提供更大的灵活性。

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

设计模式-2--工厂模式(Factory Pattern) 的相关文章

  • 如何拦截 .Net 中第三方库对非虚拟方法的调用?

    我认为我需要的是 net 人们称之为 透明动态代理 的东西 但到目前为止我所看到的所有实现 Castle DynamicProxy Spring NET AOP 等 都要求我至少执行以下操作之一 将拦截的方法声明为虚拟方法 包装类并创建包装
  • 类型转换 sockaddr 结构

    我正在尝试学习网络编程 并在这个过程中学习C 我对结构感到困惑sockaddr这是一个通用地址 并且sockaddr in 我的书里是这么说的 因此 我们可以填写 sockaddr in 的字段 然后强制转换 a 指向 它指向 指向 soc
  • 将数据集导出到 EXCEL

    我使用以下代码将数据库表中的字段导出到 Excel 中 我想要做的是能够编写一条 SQL 语句从多个表中检索字段并将其导出到 Excel 中 这段代码只允许我导出一张表 另外 如何显示保存提示对话框 示例代码将不胜感激 非常感谢 prote
  • 如何查找boost运行时版本

    我正在编写一个使用 boost 的 C 库 在这个库中 我想包含有关用于编译我的库的二进制版本的 boost 版本的信息 我可以使用宏BOOST VERSION这很好 我还想确定哪个是 boost 的运行时版本 以便我可以与用于编译我的库的
  • 加权 Voronoi 的 CGAL 2D APOLLONIUS 图 - 如何生成和获取面和顶点?

    我正在尝试根据阿波罗尼乌斯图生成加权沃罗诺伊 我正在使用 CGAL 库 我找不到如何从 apollonius 获取面和顶点的好例子 我有以下类型定义 typedef double NT typedef CGAL Cartesian lt N
  • 实体框架 - 循环更新属性

    我正在尝试找到一种方法来循环 EF 对象的属性并更新这些属性的值 更具体地说 我有 50 个字段 其中最多填充 50 个下拉列表 所有 50 个可能都需要填充 也可能不需要填充 为了解决这个问题 我有一个中继器 最多可以创建 50 个 DD
  • 多个源文件中包含包含“const”的头文件

    Why does not包含定义的头文件const并被多个源文件包含会产生编译错误multiple definition const in header file h const int num 5 int x Error Multiple
  • ApiController 操作无法从查询字符串解析数组

    使用 Visual Studio 2012 2 MVC4 Web 应用程序 我有请求发送到我的 ApiController 如下所示 http localhost api keys ids 1 ids 2 ids 3 我的印象是以下方法应该
  • C# - 如何将 IntPtr 缓冲区数据保存到文件(最快的方法)?

    我使用此代码将非托管代码中的 IntPtr 缓冲区中的字节保存到文件中 这是一个简单的回调函数 private void callback IntPtr buffer int length byte bytes new byte lengt
  • WIX 自动生成 GUID *?

    假设我生成产品 ID 为 的 WIX XML 文件 另外 对于每个组件 GUID 我都使用
  • c#Registry to XML无效字符问题

    我在尝试从注册表创建 XML 文件时遇到问题 在我的笔记本电脑 W7 64b 上它工作正常 生成了 xml 文件 但在另一台计算机 Xp 32b 上抛出异常 System ArgumentException 十六进制值 0x00 是无效字符
  • 标准头文件中的 C 编译器错误 - 未定义的 C++ 定义

    我正在尝试编译 C 程序 但收到许多错误 这些错误是在标准 C 头文件 inttypes h stdio h stat h 等 中遇到的 错误的来源是以下未定义的常量 BEGIN DECLS END DECLS BEGIN NAMESPAC
  • 如何使用 Caliburn.Micro MVVM 将焦点设置到控件

    我有一个表单 我想在发生某些用户操作时将焦点设置到文本框 我知道 MVVM 的处理方式是绑定到 VM 属性 但是 TextBox 没有允许这种情况发生的属性 从虚拟机设置焦点的最佳方法是什么 我创建了一个 IResult 实现 可以很好地实
  • 如何使用包含的转换的排名来比较两个标准转换序列

    include
  • 如何带参数调用外部程序?

    我想在我的代码中调用一个 Windows 程序 并使用代码本身确定的参数 我不想调用外部函数或方法 而是调用 WinXP 环境中的实际 exe 或批处理 脚本文件 C 或 C 将是首选语言 但如果使用任何其他语言更容易完成此操作 请告诉我
  • 选择要重写哪个基类的方法

    鉴于以下情况 class Observer public virtual void Observe Parameter p 0 template
  • 什么是多重重继承?

    我将以下称为 多重重新继承 直接继承一个类一次 并通过继承其一个或多个后代来间接继承一次或多次 通过继承一个类的两个或多个后代来间接继承一个类两次或多次 我想知道它是否存在以及如何明确访问嵌入的子对象 1 Professional C 2n
  • 为什么C#不支持多重继承? [复制]

    这个问题在这里已经有答案了 可能的重复 C 应该包含多重继承吗 https stackoverflow com questions 191691 should c include multiple inheritance 为什么C 不支持多
  • 在 WPF 树视图中获取 FullPath?

    如果我以编程方式创建 WPF TreeView 例如 TreeView treeView lt added in the designer TreeViewItem rootNode new TreeViewItem rootNode He
  • 你将如何开始自动化我的工作? - 第2部分

    后续这个问题 https stackoverflow com questions 2796128 how would you start automating my job 在经历了第一波进货 9 小时的复制 粘贴 后 我现在相信我已经满足

随机推荐

  • 微信小程序部署到线上环境

    微信小程序部署到线上环境 一 微信小程序申请 申请 并认证 未认证不能发布 认证需要300元 目前只支持企业认证 详细见官网说明 https mp weixin qq com cgi bin registermidpage action i
  • mac os mysql忘记root密码_mac上mysql报错以及root密码忘记解决办法

    1 对于前者ERROR 2002 HY000 Can t connect to local MySQL server through socket tmp mysql sock 2 这个错误 一般是mysql服务没开 命令行下执行sudo
  • java8的时期和时间

    文章目录 旧版日期时间的问题 新版日期时间介绍 Java util date java sql date SimpleDateFormatter calendar java8日期 DateTimeFormatter 计算 java8之前 j
  • Python学习 第五章 图形界面设计

    第五章 图形界面设计 1 常用的 Python GUI 库 1 1 Tkinter 1 2 wxPython 1 3 创建GUI程序 2 创建Windows窗口 3 几何布局管理器 3 1 pack 包装 3 2 grid 网格 3 3 p
  • leetcode移动零c++

    给定一个数组 nums 编写一个函数将所有 0 移动到数组的末尾 同时保持非零元素的相对顺序 示例 输入 0 1 0 3 12 输出 1 3 12 0 0 说明 必须在原数组上操作 不能拷贝额外的数组 尽量减少操作次数 整体思路 题目中都出
  • 软件项目经理的基本职责

    软件项目经理的基本职责 1 制定项目计划 并根据各种变化修改项目计划2 实施 项目的管理 开发 质量保证过程 确保客户的成本 进度 绩效和质量目标 3 制定有效的项目决策过程4 确保在项目生命周期中遵循是实施公司的管理和质量政策5 选择一个
  • VC++ CComboBox自绘(选择下拉列表框)

    效果图 头文件定义 CSWCheckComboBox h pragma once class CSWCheckComboBox public CComboBox DECLARE DYNAMIC CSWCheckComboBox 成员私有结构
  • gdal解析tif

    bool HandleTif ReadTif tif文件读取 std string name D XX xx tif const char charName name c str 注册 GDALAllRegister 以防中文名不能正常读取
  • Docker本地镜像推送到私有库

    Docker Registry是官方提供的工具 可以用于构建私有镜像仓库 1 下载镜像Docker Registry docker pull registy 2 运行私有库Registry 相当于本地有个私有Docker hub docke
  • 计算机基础——Excel 2010

    天软备考交流群 365218976 1 Excel 2010的基本操作 1 1 Excel的窗口界面 1 2 工作簿与工作表 1 3 单元格区域的管理 1 4 工作表的管理 1 5 输入和编辑数据 1 6 行 列和单元格的管理 1 7 批注
  • java代码引用jar包中文件的方法

    jar是一个单独的文件 里面的文件称之为资源 有两种方法获取 里面的资源文件 一般将资源文件放到resources文件夹中 1 推荐 静态和非静态方法中都能用 ClassName class getClassLoader getResour
  • 刷脸支付服务商抓住机会迎头赶上

    科技改变未来并不是一句口号 就拿买东西来讲 以前人们都是一手交钱一手交货 拿到大额的纸币 还要验真假 而现在移动支付成为主要付款方式 只要一部手机 扫一扫就能付款 一开始也有很多人不习惯手机支付 因为觉得没有现金实在 整天就是一堆数字转来转
  • 前端手写(正则、字符串、函数)

    1 实现千位分隔符 保留三位小数 parseToMoney 1234 56 return 1 234 56 parseToMoney 123456789 return 123 456 789 parseToMoney 1087654 321
  • ajax 传回underfined,$.jquery ajax返回的数据(json)显示为’undefined’

    这里我有一个简单的 PHP脚本 它以json格式显示数据库中的一些值 source GET source query MysqL query SELECT FROM images WHERE big thumb source results
  • Anaconda安装教程及numpy环境配置

    一 下载Anaconda 下载地址 https www anaconda com 二 安装Anaconda 1 进入官网后 看不懂英文可以先将网页翻译成中文 然后点击产品 gt 个人版 如图进入下载页面 2 可以直接点击下载 也可以滚动到页
  • 并发编程----4.java并发包中线程池的原理研究

    并发编程 4 java并发包中线程池的原理研究 java并发包中线程池ThreadPoolExecutor的原理研究 线程池的优点 线程的复用 减少线程创建和销毁带来的消耗 提供了一种资源限制和线程管理的手段 比如限制线程的个数和动态新增线
  • 数据库常用工具

    定期对你的MYSQL数据库进行一个体检 是保证数据库安全运行的重要手段 因为 好的工具是使你的工作效率倍增 常用工具 1 mysql 该mysql不是指mysql服务 而是指mysql的客户端工具 语法 mysql options data
  • 官方系统镜像烧写(windows下使用OTG)

    目录 OTG系统烧写 为什么能通过VBS将系统烧写进去呢 OTG系统烧写 选择对应的烧写工具 USB OTG线连接好 双击即可进行烧写 注意 当然也可以烧写到SD卡里面 前面我们烧写裸机代码都是选择从SD卡启动 Mfgtool这个工具先向板
  • unity官方demo学习之Stealth(二)警报灯设定

    为light alarm directional添加脚本DoneAlarmLight AlarmLight cs using UnityEngine using System Collections public class DoneAla
  • 设计模式-2--工厂模式(Factory Pattern)

    一 什么是工厂模式 工厂模式 Factory Pattern 是一种创建型设计模式 它提供了一种创建对象的接口 但是将对象的实例化过程推迟到子类中 工厂模式允许通过调用一个共同的接口方法来创建不同类型的对象 而无需暴露对象的实例化逻辑 工厂