面向对象设计与分析(42)工厂方法模式

news2024/9/25 17:21:58

文章目录

    • 定义
    • 示例
    • 实际应用

定义

工厂方法模式,定义一个用于创建对象的接口(工厂方法),返回对象基类,让子类去实现该接口,从而返回具体的子类对象。
在这里插入图片描述
结构
工厂方法模式包含以下主要角色:

  • 抽象产品(Product):定义产品的接口,是工厂方法模式创建的对象的超类型。
  • 具体产品(Concrete Product):实现抽象产品接口的具体类。
  • 抽象工厂(Creator):声明创建产品对象的工厂方法,是工厂方法模式的核心。
  • 具体工厂(Concrete Creator):实现抽象工厂接口,返回具体产品的实例。

工作原理

  1. 客户端通过调用抽象工厂中的工厂方法来创建产品对象,而不需要关心具体产品是如何创建的。
  2. 具体工厂实现了抽象工厂中的工厂方法,根据客户端的需求创建具体产品对象。
  3. 具体产品是抽象产品的具体实现,它们实现了抽象产品定义的接口。

示例

以下是一个简单的 C++ 示例:

#include <iostream>

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

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

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

// 抽象工厂类
class Creator {
public:
    virtual ~Creator() {}
public:
    virtual Product* factoryMethod() const = 0;
};

// 具体工厂类 A
class ConcreteCreatorA : public Creator {
public:
    Product* factoryMethod() const override {
        return new ConcreteProductA();
    }
};

// 具体工厂类 B
class ConcreteCreatorB : public Creator {
public:
    Product* factoryMethod() const override {
        return new ConcreteProductB();
    }
};

int main() {
    // 使用具体工厂 A 创建具体产品 A
    Creator* creatorA = new ConcreteCreatorA();
    Product* productA = creatorA->factoryMethod();
    productA->operation();
    delete creatorA;
    delete productA;

    // 使用具体工厂 B 创建具体产品 B
    Creator* creatorB = new ConcreteCreatorB();
    Product* productB = creatorB->factoryMethod();
    productB->operation();
    delete creatorB;
    delete productB;

    return 0;
}

在这个示例中,Product 是抽象产品类,定义了产品的操作接口。ConcreteProductA 和 ConcreteProductB 是具体产品类,分别实现了抽象产品类的接口。Creator 是抽象工厂类,定义了工厂方法 factoryMethod(),负责创建产品对象。ConcreteCreatorA 和 ConcreteCreatorB 是具体工厂类,分别实现了工厂方法,用于创建具体产品 A 和 B。客户端通过具体工厂类来创建具体产品对象,而不需要直接与具体产品类交互。

实际应用

该模式的缺点显而易见,我们需要为每一类Product定义一个Creator类,同时需要为每个具体的Product实现具体的Creator类,十分繁琐。

当然,我们可以通过参数化工厂方法来解决这一问题,这又绕回到了简单工厂模式:

// 工厂类
class SimpleFactory {
public:
    static Product* createProduct(char type) {
        if (type == 'A') {
            return new ConcreteProductA();
        } else if (type == 'B') {
            return new ConcreteProductB();
        }
        return nullptr;
    }
};

createProduct方法通过传递不同的参数来实例化不同的子类。

我们可以借助模板,来避免反复编写重复的Creator类:

class Creator {
	public:
		virutal	~Creator() = default;
	public:
		virtual Product* CreateProduct() = 0;
};

template<typename Product>
class StandardCreator : public Creator {
	public:
		virtual Product* CreateProduct() {
			return new Product;
		}
};

当然,还是有一定的缺陷,只能使用无参构造,或者说只能使用一种类型的构造。

实际工程里,我经常把工厂方法内嵌到产品类中,这样不用工厂类。

class Product {
	public:
		~Product() = default;
};

class ConcreateProduct {
	public:
		~Product() = default;
    public:
    	static ConcreateProduct* CreateConcreateProduct() {
            return new ConcreateProduct;
        }
};

工厂方法是static的,因此可以脱离对象调用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1615689.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

干货:40个数据统计和分析的术语,让你的可视化大屏有理有据

1. 总体&#xff08;Population&#xff09;&#xff1a;指研究对象的全体&#xff0c;即研究问题所涉及的所有个体或事物的集合。 2. 样本&#xff08;Sample&#xff09;&#xff1a;从总体中选取的一部分个体或事物&#xff0c;用于代表总体进行研究。 3. 参数&#xff08…

java-Arrays

一、Arrays的概述 Arrays是操作数组的工具类 二、Arrays的常用方法 Arrays的常用方法基本上都被static静态修饰&#xff0c;因此在使用这些方法时&#xff0c;可以直接通过类名调用 1.toString 语法&#xff1a;Arrays.toString(数组) 用于将数组的元素转换为一个字符串&a…

世界读书日:探索阅读的多样性样性——漫画、图解、图形化立体图书

在当今信息爆炸的时代&#xff0c;阅读已经不再局限于传统的书籍形式。随着科技的发展和文化的多样化&#xff0c;人们可以通过多种形式来获取知识和享受阅读的乐趣。从漫画、图解到图形化立体图书&#xff0c;每一种形式都有其独特的魅力&#xff0c;适合不同类型的读者和学习…

软件公司:饥一顿饱一顿,咋办?试一试外部柔性产能。

有人开玩笑&#xff0c;软件公司最理想状态就是&#xff1a;项目来了&#xff0c;公司有足够的人力消化产能&#xff1b;项目没了&#xff0c;人员都走了&#xff0c;不会造成产能搁置。 以上是个理想状态&#xff0c;事实上单纯依靠一个公司是做不到的&#xff0c;所以一定建立…

2024普通人怎么搞钱?2024创业好项目!2024创业小白适合做什么生意!

先讲几个残酷的数据&#xff0c;滴滴用户从4500万跌到了1000万&#xff0c;打车的人少了3/4&#xff0c;携程用户旅游业从2600万跌到了600万&#xff0c;少了3/4&#xff0c;怪兽充电宝用户从300万跌到了100万&#xff0c;商场逛街少了2/3&#xff0c;星巴克的用户月活之前是40…

spi 收发流程

patch日期 收发流程的重大修改&#xff0c;来源于2012年的如下补丁 内核提交收发流程的patch spi: create a message queueing infrastructure - kernel/git/stable/linux.git - Linux kernel stable tree 源代码路径及功能 源码作用\drivers\spi\spi.cspi 通用接口&#x…

中小企业有必要建数字档案室吗?

中小企业有建立数字档案室的必要性取决于企业的具体情况和需求。以下是一些考虑因素&#xff1a; 1. 节省空间和成本&#xff1a;传统的纸质档案需要大量的物理空间和维护成本。建立数字档案室可以大大节约空间和减少纸质文档的使用&#xff0c;从而降低相关成本。 2. 提高文件…

数据持久化第四课-EF的基本使用

数据持久化第四课-EF的基本使用 一.预习笔记 1.数据实体模型概述 ORM全称是“对象-关系映射”&#xff08;Object-Relation Mapping&#xff09; ORM是将关系数据库中的数据用对象的形式表现出来&#xff0c;并通过面向对象的方式将这些对象组织起来&#xff0c;实现系统业务…

【RT-Thread应用笔记】FRDM-MCXN947上的RW007实践——WiFi延迟和带宽测试

【RT-Thread应用笔记】FRDM-MCXN947上的RW007实践——WiFi延迟和带宽测试 一、背景介绍1.1 RW007模组简介1.2 Arduino接口简介1.3 RW007软件包简介1.4 RT-Thread env工具简介 二、创建工程2.1 新建工程2.2 添加rw007软件包2.3 打开RW007配置项2.4 启用pin驱动2.5 禁用rw007的ST…

mysql基础19——日志

日志 mysql的日志种类非常多 通用查询日志 慢查询日志 错误日志 与时间有关联 二进制日志 中继日志 与主从服务器的同步有关 重做日志 回滚日志 与数据丢失有关 通用查询日志 记录了所有用户的连接开始时间和截至时间 以及给mysql服务器发送的所有指令 当数据异常时&…

【Yolov系列】Yolov5学习(一)补充1.1:自适应锚框计算

1、Yolov5的网络结构 Yolov5中使用的Coco数据集输入图片的尺寸为640*640&#xff0c;但是训练过程的输入尺寸并不唯一&#xff0c;Yolov5可以采用Mosaic增强技术把4张图片的部分组成了一张尺寸一定的输入图片。如果需要使用预训练权重&#xff0c;最好将输入图片尺寸调整到与作…

实战 | 无视杀软使用远控工具进行横向移动Tips

实战 | 无视杀软使用远控工具进行横向移动Tips。 在有杀软拦截&#xff0c;CS无法上线的情况下&#xff0c;经常用到todesk和向日葵这两个远控工具进行横向移动。不过这两个工具现在好像不怎么好用了。不过无所谓&#xff0c;用其他的就是了&#xff0c;听说最近GotoHTTP很火&…

机器人实验室LAAS-CNRS介绍

一、LAAS-CNRS介绍 1、缩写介绍 同样的&#xff0c;给出英文缩写的全称&#xff0c;以便理解。这里的LAAS&#xff08;Laboratory for Analysis and Architecture of Systems&#xff09;指法国的系统分析与架构实验室&#xff0c;CNRS&#xff08;Centre National de la Rec…

网络数据包嗅探器工具

组织的网络非常庞大&#xff0c;包含服务器、交换机、路由器和接入点等众多节点&#xff0c;由于许多资源和流量不断通过这些节点&#xff0c;因此很难确定大量流量是真实的还是安全攻击的迹象&#xff0c;了解和了解组织的网络流量至关重要&#xff0c;一个有用的资源是网络数…

vivado 自定义波形配置

自定义配置 您可使用下表中列示并简述的功能来自定义波形配置 &#xff1b; 其中功能名称链接至提供功能完整描述的相应小节。 光标 光标主要用作为样本位置的临时指示符并且会频繁移动 &#xff0c; 比如测量 2 个波形边沿之间的距离 &#xff08; 以样本数为单位 &#x…

STM32与ASRPRO通信(智能家居系列一)

本片文章主要讲一下STM32单片机和ASRPRO是如何进行串口通信的&#xff0c;具体过程代码和实验结果等会一并给大家复现在本篇文章当中。 一、 STM32端&#xff08;首先介绍stm32端需要用到的端口和代码如何进行操作&#xff09; 根据官方给出的原理图&#xff1a; 根据原理图我们…

XV6源码阅读——页表

文章目录 前言分页硬件实际转换 内核地址空间 前言 一个本硕双非的小菜鸡&#xff0c;备战24年秋招。打算尝试6.S081&#xff0c;将它的Lab逐一实现&#xff0c;并记录期间心酸历程。 代码下载 官方网站&#xff1a;6.S081官方网站 分页硬件 RISC-V指令&#xff08;用户和内…

mysql基础3——创建和修改数据表

创建数据表 创建一个表&#xff08;importtype有默认值1&#xff09;并插入一条数据&#xff08;importtype字段没有指定值&#xff09; 约束 默认约束&#xff08;把设置的默认值自动赋值给字段&#xff09; create table demo.importhead(listnum int,supplied int,stock…

Colab使用教程(超级详细版)及Colab Pro/Pro+评测

原文&#xff1a;Colab使用教程&#xff08;超级详细版&#xff09;及Colab Pro/Pro评测 - 知乎 在下半年选修了机器学习的关键课程Machine learning and deep learning&#xff0c;但由于Macbook Pro显卡不支持cuda&#xff0c;因此无法使用GPU来训练网络。教授推荐使用Google…

【LAMMPS学习】八、基础知识(3.6)计算热导率

8. 基础知识 此部分描述了如何使用 LAMMPS 为用户和开发人员执行各种任务。术语表页面还列出了 MD 术语&#xff0c;以及相应 LAMMPS 手册页的链接。 LAMMPS 源代码分发的 examples 目录中包含的示例输入脚本以及示例脚本页面上突出显示的示例输入脚本还展示了如何设置和运行各…