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.mzph.cn/news/804245.shtml

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

相关文章

人工智能——深度学习

4. 深度学习 4.1. 概念 深度学习是一种机器学习的分支&#xff0c;旨在通过构建和训练多层神经网络模型来实现数据的高级特征表达和复杂模式识别。与传统机器学习算法相比&#xff0c;深度学习具有以下特点&#xff1a; 多层表示学习&#xff1a;深度学习使用深层神经网络&a…

麒麟KOS删除鼠标右键新建菜单里不需要的选项

原文链接&#xff1a;麒麟KOS删除鼠标右键新建菜单里不需要的选项 Hello&#xff0c;大家好啊&#xff01;在日常使用麒麟KOS操作系统时&#xff0c;我们可能会发现鼠标右键新建菜单里包含了一些不常用或者不需要的选项。这不仅影响我们的使用效率&#xff0c;也让菜单显得杂乱…

新能源电力行业设备点巡检系统的应用

新能源电力行业正日益成为全球能源结构的重要支柱&#xff0c;其设备点巡检系统作为确保电力设施安全、高效运行的关键环节&#xff0c;正受到业界的广泛关注和应用。 设备点巡检系统是一种集数据采集、实时监控、智能分析于一体的现代化管理工具。在新能源电力行业中&#xff…

Java常见算法_常见的查找算法和排序算法——简介及代码演示

在本文中我将介绍Java中的常见算法&#xff0c;查找算法包括基本查找、二分查找、插值查找和分块查找。排序算法包括冒泡排序、选择排序、插入排序和快速排序 查找算法&#xff1a; 1.基本查找&#xff1a; 代码&#xff1a; public class BasicSearchDemo {public static …

SpringMVC:搭建第一个web项目并配置视图解析器

&#x1f449;需求&#xff1a;用spring mvc框架搭建web项目&#xff0c;通过配置视图解析器达到jsp页面不得直接访问&#xff0c;实现基本的输出“hello world”功能。&#x1f469;‍&#x1f4bb;&#x1f469;‍&#x1f4bb;&#x1f469;‍&#x1f4bb; 1 创建web项目 1…

如何解决Python包管理问题:ERROR: Could not find a version that satisfies the requirement

如何解决Python包管理问题&#xff1a;“ERROR: Could not find a version that satisfies the requirement” 文章目录 如何解决Python包管理问题&#xff1a;“ERROR: Could not find a version that satisfies the requirement”错误描述问题分析解决方案检查包名确保网络连…

【JVM】面试题汇总

JVM1. 什么是JVM&#xff1f;2. 了解过字节码文件的组成吗&#xff1f;3. 什么是运行时数据区4. 哪些区域会出现内存溢出5. JVM在JDK6-8之间在内存区域上有什么不同 6. 类的生命周期 7. 什么是类加载器&#xff1f;类加载器有哪几种 8. 什么是双亲委派机制&#xff1f;有什么好…

“国字号”荣誉、全国试点,侨乡群众身边的“放心”公证处

日前&#xff0c;我市五邑公证处获评“全国公共法律服务工作先进集体”称号。 走进公证处&#xff0c;首先映入眼帘的是一间宽敞明亮的大厅&#xff0c;办证点内还设置多个独立办证室&#xff0c;工作人员热情地为前来办理业务的市民提供专业、人性化的公证服务。江门市五邑公证…

Windows上面搭建Flutter Android运行环境

Flutter Android环境搭建 电脑上面安装配置JDK电脑上下载安装Android Studio电脑上面下载配置Flutter Sdk &#xff08;避坑点一&#xff09;下载SDK配置对应的环境变量 到path 电脑上配置Flutter国内镜像运行 flutter doctor命令检测环境是否配置成功创建运行Flutter项目&…

ARM单片机的GPIO口在控制不同LED、按键时的设置

个人备忘&#xff0c;不喜勿喷。 GPIO口在驱动共阴极、共阳极LED灯时需要不同的初始化设置 对于这一类的led灯&#xff1a; 最好选择推挽、上拉、高速输出&#xff0c;同时IO口初始化时需要拉高。 上面这种需要下拉输入&#xff1b; 上图这种需要上拉输入&#xff0c;这样才…

vue点击上传图片并实现图片预览功能,并实现多张图片放到一个数组中进行后端请求(使用原生input)

一、将 File 对象转成 BASE64 字符串 &#xff08;FileReader&#xff09; <template><div><!-- 用来显示封面的图片 --><!-- <img src"/assets/images/cover.jpg" alt"" class"cover-img" ref"imgRef" />…

html基础(2)(链接、图像、表格、列表、id、块)

1、链接 <a href"https://www.example.com" target"_blank" title"Example Link">Click here</a> 在上示例中&#xff0c;定义了一个链接&#xff0c;在网页中显示为Click here&#xff0c;鼠标悬停指示为Example Link&#xff0c…

Java(多线程)

一、基本概念 进程&#xff1a;一个具有一定独立功能的程序关于某个数据集合的一次运行活动。它是操作系统动态执行的基本单元&#xff0c;在传统的操作系统中&#xff0c;进程既是基本的分配单元&#xff0c;也是基本的执行单元。线程&#xff1a;操作系统中能够进行运算的最…

java Web课程管理系统用eclipse定制开发mysql数据库BS模式java编程jdbc

一、源码特点 JSP 课程管理系统是一套完善的web设计系统&#xff0c;对理解JSP java 编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,eclipse开发&#xff0c;数据库为Mysql5.0&#xff0c;使用ja…

贪心算法|406.根据身高重建队列

力扣题目链接 class Solution { public:static bool cmp(const vector<int>& a, const vector<int>& b) {if (a[0] b[0]) return a[1] < b[1];return a[0] > b[0];}vector<vector<int>> reconstructQueue(vector<vector<int>…

骑砍2霸主MOD开发(2)-基础开发环境搭建

一.骑砍2霸主程序架构 二.骑砍2霸主C#接口层代码查看 1.C#反编译工具dnspy下载: 2.骑砍2霸主游戏引擎接口查看: 例如IMBAgent interface接口: #调用TaleWorlds.Native.dll中的函数 [EngineMethod("get_movement_flags", false)] uint GetMovementFlags(UIntPtr agen…

Visual Studio Code SSH 连接远程服务器

Visual Studio Code通过 SSH 连接远程服务器并实现免密登录&#xff0c;你可以按照以下步骤进行操作&#xff1a; 1. **安装插件**&#xff1a;首先&#xff0c;在 VS Code 中安装 "Remote - SSH" 插件。打开 VS Code&#xff0c;点击左侧的扩展图标&#xff0c;搜索…

微服务学习3

目录 1.微服务保护 1.1.服务保护方案 1.1.1.请求限流 1.1.2.线程隔离 1.1.3.服务熔断 1.2.Sentinel 1.2.1.微服务整合 1.2.2.请求限流 1.3.线程隔离 1.3.1.OpenFeign整合Sentinel 1.3.2.配置线程隔离 1.4.服务熔断 1.4.1.编写降级逻辑 1.4.2服务熔断 2.分布式事…

mp4转flv怎么转?电脑怎么把视频转成flv?

MP4&#xff08;MPEG-4 Part 14&#xff09;是一种多媒体容器格式&#xff0c;广泛用于包含视频、音频、字幕等多种数据流。MP4因其高度灵活性、压缩效率和兼容性成为视频领域的主流格式&#xff0c;支持范围涵盖从在线视频到移动设备的各类应用场景。 FLV文件格式的多个优点 …

scFed:联邦学习用于scRNA-seq分类

scRNA-seq的出现彻底改变了我们对生物组织中细胞异质性和复杂性的理解。然而&#xff0c;大型&#xff0c;稀疏的scRNA-seq数据集的隐私法规对细胞分类提出了挑战。联邦学习提供了一种解决方案&#xff0c;允许高效和私有的数据使用。scFed是一个统一的联邦学习框架&#xff0c…