C++设计模式:抽象工厂模式(七)

1、定义与动机
  • 抽象工厂定义:提供一个接口,让该接口负责创建一系列“相关或者相互依赖的对象”,无需指定它们具体的类
  • 动机:
    • 在软件系统中,经常面临着“一系列相互依赖的对象”的创建工作;同时,由于需求的变化,往往存在更多系列对象的创建工作。
    • 如何应对这种变化?如何绕过常规的对象创建方法(new),提供一种“封装机制来避免客户程序和这种“多系列具体对象创建工作”的紧耦合?
  • 个人理解:在工厂方法的基础上套上了一层封装接口,封装的意义就是为了在工厂方法的基础上返回一套或者同类的相互依赖的一系列对象!
2、案例分析

假设现在有一个DAO层需要获取员工的信息,通过数据库访问获取数据。

2.1、普通代码结构(一)
  • 很容易编写出这样一份朴素简单的代码
  • 分析下面这份代码存在的问题:
    • 首先很明显的可以发现这里存在紧耦合,不符合工厂方法模式
    • 一旦需要换数据库源,这两个new对象就需要更改硬编码(违背开闭原则)
    • 因此可能很容易的发现通过工厂方法模式来优化这个代码
#include <vector>
class EmployeeMapper{
public:vector<EmployeeDO> GetEmployees(){SqlConnection* connection = new SqlConnection();connection->ConnectionDB("...");SqlCommand* command = new SqlCommand();command->CommandSQL("....");// .....}
};
2.2、工厂方法(二)
  • SqlConnector:ConnectionDB操作提炼一个抽象方法,然后给MySQLConnectDB和OracleConnectDB继承并且实现连接的具体操作
  • ConnectorFactory:连接对象创建工厂,然后MySQLConnectorFactory和OracleConnectorFactory分别继承并且创建各自的实例化对象
  • SqlCommand和CommanderFactory的实现方式同上。这样就完美的隔离了紧耦合的绑定
  • 一旦需要增加一种数据源只需要编写XXXConnectDB、XXXConnectorFactory和XXXCommand、XXXCommanderFactory。很明显拓展是开放的,修改关闭
//
// Created by splay on 24-4-9.
//
#include <vector>
class SqlConnector{
public:virtual void ConnectionDB(string info) = 0;virtual ~SqlConnector(){}
};
class MySQLConnector: public SqlConnector{
public:virtual void ConnectionDB(string info){}
};class OracleConnector: public SqlConnector{
public:virtual void ConnectionDB(string info){}
};class ConnectorFactory{
public:virtual SqlConnector* CreateConnector() = 0;virtual ~ConnectorFactory(){}
};
class MySQLConnectorFactory: public ConnectorFactory{
public:virtual SqlConnector* CreateConnector(){SqlConnector* mysqlConnector = new MySQLConnector();return mysqlConnector;}
};class OracleConnectorFactory: public ConnectorFactory{
public:virtual SqlConnector* CreateConnector(){SqlConnector* oracleConnector = new OracleConnector();return oracleConnector;}
};class SqlCommand{
public:virtual void CommandSQL(string sql) = 0;virtual ~SqlCommand(){}
};
class MySQLCommand: public SqlCommand{
public:virtual void CommandSQL(string sql){}
};
class OracleCommand: public SqlCommand{
public:virtual void CommandSQL(string sql){}
};class CommanderFactory{
public:virtual SqlCommand* CreateCommander() = 0;virtual ~CommanderFactory(){}
};
class MySQLCommanderFactory: public CommanderFactory{
public:virtual SqlCommand* CreateCommander(){SqlCommand* mySqlCommand = new MySQLCommand();return mySqlCommand;}
};class OracleCommanderFactory: public CommanderFactory{
public:virtual SqlCommand* CreateCommander(){SqlCommand* oracleCommand = new OracleCommand();return oracleCommand;}
};class EmployeeMapper{
private:ConnectorFactory* connectorFactory;CommanderFactory* commanderFactory;
public:vector<EmployeeDO> GetEmployees(){SqlConnector* connector = connectorFactory->CreateConnector();connector->ConnectionDB("...");SqlCommand* command = commanderFactory->CreateCommander();command->CommandSQL("....");// .....}
};
3、抽象工厂模式
  • 工厂方法帮助我们解决了这份代码的的耦合问题,达到了松耦合的层次,但是并没有高内聚

  • 工厂方法实现的这个代码好吗,其实它并不完美,不完美的点在于Connector和Commander是来自同一种数据库

  • 如果传入MySQLConnectorFactory和OracleCommanderFactory,会导致Connector和Commander来自不同的数据源,很明显这里存在一定的风险隐患。

  • 抽象工厂的核心:在工厂方法的前提下,解决一系列相关联对象的创建问题,使得有关联性的对象具有高度的内聚性

  • 提炼一个DBFactory接口,

    • 里面包含创建CreateConnector、CreateCommander的虚方法
    • 对于不同的数据库源继承这个DBFactory并且实现这两个创建对象的方法
    • 在需要的地方注入抽象工厂,通过抽象工厂创建**同类(相关联)**对象
#include <vector>
class SqlConnector{
public:virtual void ConnectionDB(string info) = 0;virtual ~SqlConnector(){}
};
class SqlCommand{
public:virtual void CommandSQL(string sql) = 0;virtual ~SqlCommand(){}
};
class MySQLConnector: public SqlConnector{
public:virtual void ConnectionDB(string info){}
};
class MySQLCommand: public SqlCommand{
public:virtual void CommandSQL(string sql){}
};class OracleConnector: public SqlConnector{
public:virtual void ConnectionDB(string info){}
};
class OracleCommand: public SqlCommand{
public:virtual void CommandSQL(string sql){}
};class DBFactory{
public:virtual SqlConnector* CreateConnector() = 0;virtual SqlCommand* CreateCommander() = 0;virtual ~DBFactory(){}
};class MySQLFactory: public DBFactory{
public:virtual SqlConnector* CreateConnector(){SqlConnector* mysqlConnector = new MySQLConnector();return mysqlConnector;}virtual SqlCommand* CreateCommander(){SqlCommand* mySqlCommand = new MySQLCommand();return mySqlCommand;}
};class OracleFactory: public DBFactory{
public:virtual SqlConnector* CreateConnector(){SqlConnector* oracleConnector = new OracleConnector();return oracleConnector;}virtual SqlCommand* CreateCommander(){SqlCommand* oracleCommand = new OracleCommand();return oracleCommand;}
};class EmployeeMapper{
private:DBFactory *dbFactory;
public:vector<EmployeeDO> GetEmployees(){SqlConnector* connector = dbFactory->CreateConnector();connector->ConnectionDB("...");SqlCommand* command = dbFactory->CreateCommander();command->CommandSQL("....");// .....}
};
4、总结
  • 如果没有应对“多系列对象构建”的需求变化,则没有必要使用Abstract Factory模式,这时候使用简单的工厂方法模式完全可以

  • “系列对象”指的是在某一特定系列下的对象之间有相互依赖或者作用的关系,不同系列的对象之间不能相互依赖。

  • Abstract Factory模式主要在于应对“新的一系列”的需求变动。其缺点在于难以应对“新对象”的需求变动
    在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

从ChatGPT到多模态大模型:现状与未来(多模态)

ChatGPT 训练的核心技术主要包括: 预训练语言模型;有监督微调;基于人类反馈的 强 化 学 习 (ReinforcementLearningfrom Human Feedback,RLHF) 首先,通过自监督预训练使语言模型从大规模语料库中学习语言规律,具备基础 理解和生成能力;然后,通过构造指令微调数据集 并对模型进…

uniapp在发行原始云打包ios时提示私钥证书不是有效的p12文件

uniapp在发行原始云打包ios时提示私钥证书不是有效的p12文件 解决方法&#xff1a; 经过我多次的创建p12证书文件&#xff0c;然后更换设备继续创建&#xff0c;仍然存在这个问题&#xff0c;通过排查不是.p12的本身的问题&#xff0c;而是命名的问题&#xff0c;命名不能是中…

数据仓库的概念和作用?如何搭建数据仓库?

随着企业规模的扩大和数据量的爆炸性增长&#xff0c;有效管理和分析海量数据成为企业数字化转型的关键。而在互联网的普及过程中&#xff0c;信息技术已深入渗透各行业&#xff0c;逐渐融入企业的日常运营。然而&#xff0c;企业在信息化建设中面临了一系列困境和挑战&#xf…

MKS GHW-12 RF Plasma Generator Genesis 使用说明

MKS GHW-12 RF Plasma Generator Genesis 使用说明

云平台和云原生

目录 1.0 云平台 1.1.0 私有云、公有云、混合云 1.1.1 私有云 1.1.2 公有云 1.1.3 混合云 1.2 常见云管理平台 1.3 云管理的好处 1.3.1 多云的统一管理 1.3.2 跨云资源调度和编排需要 1.3.3 实现多云治理 1.3.4 多云的统一监控和运维 1.3.5 统一成本分析和优化 1.…

适用于 Mac 的 10 大数据恢复工具,具有优点、缺点

数据丢失很常见&#xff0c;并且可能由于许多不同的原因而发生。这种情况在我和我们团队的其他成员身上发生过很多次&#xff0c;即使我们格外小心我们的个人存储设备。 幸运的是&#xff0c;数据恢复软件在大多数情况下都可以工作。但是&#xff0c;由于数据丢失场景彼此之间…

主流排序简单集合

排序算法集合 选择排序 图解&#xff1a;以此类推直至 /*选择排序*/ void select_sort(vector<int>& nums) {/*选取一个基准元素逐个与后面的比较*/for (int i 0; i < nums.size() - 1-1; i) {int min i;/*定义随之变化的基准元素*/for (int j i 1; j <…

LVS+Keepalive 实现负载均衡高可用集群_lvs+keepalived

一、LVS 介绍 目前LVS已经被集成到Linux内核模块中。LVS是Linux Virtual Server的简称&#xff0c;也就是Linux虚拟服务器&#xff0c;该项目在Linux内核中实现了基于IP的数据请求负载均衡调度方案&#xff0c;终端互联网用户从外部访问公司的外部负载均衡服务器&#xff0c;终…

【项目】棋海争锋

&#x1f3a5; 个人主页&#xff1a;Dikz12&#x1f4d5;格言&#xff1a;吾愚多不敏&#xff0c;而愿加学欢迎大家&#x1f44d;点赞✍评论⭐收藏 目录 项目介绍 WebSocket介绍 使用 项目创建 数据库设计 用户模块 登录接口 注册接口 获取用户信息接口 匹配模块 …

华为S5735S核心交换配置实例

以下脚本实现创建vlan2,3&#xff0c;IP划分&#xff0c;DHCP启用&#xff0c;接口划分&#xff0c;ssh,telnet,http,远程登录启用 默认用户创建admin/admin123提示首次登录需要更改用户密码 sysname test-Hxvlan 2 description to test1…

【快捷部署】016_Ollama(CPU only版)

&#x1f4e3;【快捷部署系列】016期信息 编号选型版本操作系统部署形式部署模式复检时间016Ollama&#xff08;CPU only&#xff09;latestCentOS 7.XDocker单机2024-04-10 注意事项&#xff1a; 1、目前镜像及大模型下载速度尚可&#xff0c;但由于容量较大&#xff0c;所以…

汽车4S行业的信息化特点与BI建设挑战

汽车行业也是一个非常大的行业&#xff0c;上下游非常广&#xff0c;像主机厂&#xff0c;上游的零配件&#xff0c;下游的汽车流通&#xff0c;汽车流通之后的汽车后市场&#xff0c;整个链条比较长。今天主要讲的是汽车流通&#xff0c;汽车4S集团。一个汽车4S集团下面授权代…

gitlab、jenkins安装及使用文档二

安装 jenkins IP地址操作系统服务版本192.168.75.137Rocky9.2jenkins 2.450-1.1 jdk 11.0.22 git 2.39.3192.168.75.138Rocky9.2gitlab-ce 16.10.0 结合上文 jenkins安装 前期准备&#xff1a; yum install -y epel-release yum -y install net-tools vim lrzsz wget…

【双指针】成最多水的容器

给定一个长度为 n 的整数数组 height 。有 n 条垂线&#xff0c;第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线&#xff0c;使得它们与 x 轴共同构成的容器可以容纳最多的水。 返回容器可以储存的最大水量。 示例 1&#xff1a; 输入&#xff1a;[1,…

科技云报道:从“奇点”到“大爆炸”,生成式AI开启“十年周期”

科技云报道原创。 世界是复杂的&#xff0c;没有人知道未来会怎样&#xff0c;但如果单纯从技术的角度&#xff0c;我们总是能够沿着技术发展的路径&#xff0c;找到一些主导未来趋势的脉络。 从Sora到Suno&#xff0c;从OpenAI到Copilot、Blackwell&#xff0c;这些热词在大…

【微服务】------微服务架构技术栈

目前微服务早已火遍大江南北&#xff0c;对于开发来说&#xff0c;我们时刻关注着技术的迭代更新&#xff0c;而项目采用什么技术栈选型落地是开发、产品都需要关注的事情&#xff0c;该篇博客主要分享一些目前普遍公司都在用的技术栈&#xff0c;快来分享一下你当前所在用的技…

Java语言实现文件分割与合并

一&#xff1a; 题目&#xff1a; 写一个方法,将feige.exe文件分割为每份1MB大小的若干份(最后一份可以不满1MB), 存储在一个temp的文件夹中(每份文件名自己定义,例如1.temp 2.temp), 然后再写一个方法,将temp文件夹中的若干份合并为一个文件fg.exe 代码&#xff1a; main…

Linux查看系统配置信息的命令【lscpu】【free】【df】【uname】【lsblk】

目录 1.查看CPU信息【lscpu】 2.查看内存信息【free】 3.查看文件系统信息【df】 4.查看系统信息【uname】 知识扩展&#xff1a;Red Hat Enterprise Linux 和 Debian GNU/Linux 两者的发展介绍 知识扩展&#xff1a;Centos 和 ubuntu的区别 知识扩展&#xff1a;更多 …

51单片机入门_江协科技_25~26_OB记录的笔记_蜂鸣器教程

25. 蜂鸣器 25.1. 蜂鸣器介绍 •蜂鸣器是一种将电信号转换为声音信号的器件&#xff0c;常用来产生设备的按键音、报警音等提示信号 •蜂鸣器按驱动方式可分为有源蜂鸣器和无源蜂鸣器&#xff08;开发板上用的无源蜂鸣器&#xff09; •有源蜂鸣器&#xff1a;内部自带振荡源&a…

C语言 知识点 + 笔记(2w6千字 持续更新...)

前言 本篇以笔记为主的C语言详解,全篇一共十章内容,2万6千多字,会持续更新基础内容,争取做到更详细。多一句没有,少一句不行! 形而上学者谓之道,形而下学者谓之器 第 1 章 C语言的流程 (1) C程序经历的六个阶段 编辑(Edit)预处理(Preprocess)编译(Compile)汇编(Assemb…