【设计模式】Head First 设计模式——工厂方法模式 C++实现
设计模式最大的作用就是在变化和稳定中间寻找隔离点,然后分离它们,从而管理变化。将变化像小兔子一样关到笼子里,让它在笼子里随便跳,而不至于跳出来把你整个房间给污染掉。
设计思想
定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method 使得一个类的实例化延迟到子类。(目的:解耦,手段:虚函数)
动机
在软件系统中,经常面临着创建对象的工作;由于需求的变化,需要创建的对象的具体类型经常变化。
如何应对这种变化?如何绕过常规的对象创建方法(new),提供一种“封装机制”来避免客户程序和这种“具体对象创建工作”的紧耦合?
Factory Method模式用于隔离类对象的使用者和具体类型之间的耦合关系。面对一个经常变化的具体类型,紧耦合关系会导致软件的脆弱。
Factory Method模式通过面向对象的收发,将所要创建的具体对象工作延迟到子类,从而实现一种扩展(而非更改)的策略,较好地解决了这种耦合关系。
Factory Method 模式解决“单个对象”的需求变化。缺点在于创建方法、参数需要相同。
业务场景
在 MainForm 中需要对文件进行分解操作,但是分解的文件可能是二进制文件,文本文件,图片文件等等,这时候我们需要在 MainForm 创建对应的对象,然后调用分解函数。
一个非常直观的思路是:
class ISplitter {
public:virtual void split() = 0;virtual ~ISplitter() {}
};class BinarySplitter : public ISplitter {
//实现分解二进制文件
};class TxtSplitter : public ISplitter {
//实现分解TXT文件
};class PictureSplitter : public ISplitter {
//实现分解图片文件
};class VideoSplitter : public ISplitter {//实现分解视频文件
};class MainForm : public Form {
public:void Button1_Click() {ISplitter* splitter = new BinarySplitter(); splitter->split();}
};
这是很自然的一种写法,问题的关键在于这一句代码:
ISplitter* splitter = new BinarySplitter();
在等号的左边,是一个抽象类,属于抽象依赖(编译时依赖),但是等号的右边,是一个具体类,属于细节依赖。根据依赖倒置原则,抽象不应该依赖于细节,而这种写法很明显违背了这种原则。
下面看看使用工厂模式应该怎么去实现:
代码案例
编写专门的工厂类,再编写具体的工厂子类。在具体操作的 MainForm 中通过构造把子类对象传入。用多态的方式,避免了 MainForm 中的固定。
// 抽象类
class ISplitter {
public:virtual void split() = 0;virtual ~ISplitter() {}
};// 工厂基类
class SplitterFactory {
public:// 虚函数,延迟到运行时依赖virtual ISplitter* CreateSplitter() = 0;virtual ~SplitterFactory() {}
};//创建一个工厂类,专门负责对象的实例化// 具体类
class BinarySplitter : public ISplitter {};class TxtSplitter : public ISplitter {};class PictureSplitter : public ISplitter {};class VideoSplitter : public ISplitter {};// 具体工厂:每一个具体类都对应着一个专门生产这种对象的工厂
class BinarySplitterFactory : public SplitterFactory {
public:virtual ISplitter* CreateSplitter() {return new BinarySplitter();}
};class TxtSplitterFactory : public SplitterFactory {
public:virtual ISplitter* CreateSplitter() {return new TxtSplitter();}
};class PictureSplitterFactory : public SplitterFactory {
public:virtual ISplitter* CreateSplitter() {return new PictureSplitter();}
};class VideoSplitterFactory : public SplitterFactory {
public:virtual ISplitter* CreateSplitter() {return new VideoSplitter();}
};// MainForm 没有具体类的依赖
// 只有抽象的类的依赖
// 把依赖具体类转移了
class MainForm : public Form {SplitterFactory* factory; // 含有工厂成员public:MainForm(SplitterFactory* factory) {this->factory = factory;}//想要实例化什么样的对象,由运行时决定void Button1_Click() {ISplitter* splitter = factory->CreateSplitter(); // 多态newsplitter->split();}
};
相关文章:
【设计模式】Head First 设计模式——工厂方法模式 C++实现
设计模式最大的作用就是在变化和稳定中间寻找隔离点,然后分离它们,从而管理变化。将变化像小兔子一样关到笼子里,让它在笼子里随便跳,而不至于跳出来把你整个房间给污染掉。 设计思想 定义一个用于创建对象的接口,让子…...
【爬虫】7.2. JavaScript动态渲染界面爬取-Selenium实战
JavaScript动态渲染界面爬取-Selenium实战 爬取的网页为:https://spa2.scrape.center,里面的内容都是通过Ajax渲染出来的,在分析xhr时候发现url里面有token参数,所有我们使用selenium自动化工具来爬取JavaScript渲染的界面。 fr…...
c语言实训心得3篇集合
c语言实训心得体会一: 在这个星期里,我们专业的学生在专业老师的带领下进行了c语言程序实践学习。在这之前,我们已经对c语言这门课程学习了一个学期,对其有了一定的了解,但是也仅仅是停留在了解的范围,对里…...
2023高教社杯数学建模B题思路代码 - 多波束测线问题
# 1 赛题 B 题 多波束测线问题 单波束测深是利用声波在水中的传播特性来测量水体深度的技术。声波在均匀介质中作匀 速直线传播, 在不同界面上产生反射, 利用这一原理,从测量船换能器垂直向海底发射声波信 号,并记录从声波发射到…...
MySql 变量
1.系统变量 1.1 系统变量分类 变量由系统定义,不是用户定义,属于 服务器 层面。系统变量分为全局系统变量(需要添加 global 关键字)以及会话系统变量(需要添加 session 关键字),有时也把全局系…...
2023-简单点-make和build都是什么东西?
make make命令根据makefile.txt中的命令进行批量处理。 编译时自动检查文件是否更新,如果文件已经更改,make会对他重新编译,否则跳过。 编译选定的目标,但是Make只编译上次编译变化过的文件,减少重复劳动࿰…...
Nginx 学习(八)Nginx实现用IP测试灰度发布
1.1 问题 配置Nginx使其可以将动态访问转交给uWSGI: 1.2 方案 安装Python工具及依赖 安装uWSGI并编写配置文件 1.3 步骤 实现此案例需要按照如下步骤进行。 步骤一: 1)安装python依赖软件[rootproxy python]# yum -y install gcc make pytho…...
QT 自定义信号
自定义信号,需要 1.在singnals:区域下写信号函数,以及函数对应的参数 2. 需要emit关键字进行发射信号 3. 在需要处理该信号的其他类中,建立信号和其信号槽函数connect() 4. 在其他类中创建信号处理槽函数 #include "mythread.h"my…...
注解方式配置SpringMVC
注解配置SpringMVC 1. 初始化类,代替web.xml2. 创建SpringConfig配置类,代替spring的配置文件3. 创建SpringMVCConfig配置类,代替SpringMVC.xml配置文件4. 项目结构 1. 初始化类,代替web.xml Spring3.2引入了一个便利的WebApplic…...
2023年限售股解禁研究报告
第一章 概述 解禁是指限售流通股过了限售承诺期,可以在二级市场自由买卖的过程。根据流通性质,可将上市公司股份分为有限售条件的流通股(“限售流通股”)及无限售条件的流通股(“流通股”)。 限售流通股指…...
『PyQt5-Qt Designer篇』| 08 Qt Designer中容器布局和绝对布局的使用
08 Qt Designer中容器布局和绝对布局的使用 1 容器布局1.1 设计容器布局1.2 保存文件并执行2 绝对布局2.1 设计绝对布局2.2 保存文件并执行1 容器布局 1.1 设计容器布局 先拖入一个容器Frame容器,然后拖入几个控件: 把拖入的控件拖入容器中: 选中容器,右键-布局-栅格布局:…...
Android 下第一个fragment app 先Java 后Kotlin
看着视频学习的,Fragment:3.Fragment使用方法_哔哩哔哩_bilibili 程序的运行效果是,手机页面有2个fragment,每个fragment 有一个text view,一个按钮,按一下显示,fine,and you?,各自…...
行业追踪,2023-09-04
自动复盘 2023-09-04 凡所有相,皆是虚妄。若见诸相非相,即见如来。 k 线图是最好的老师,每天持续发布板块的rps排名,追踪板块,板块来开仓,板块去清仓,丢弃自以为是的想法,板块去留让…...
Android MQTT:实现设备信息上报与远程控制
Android MQTT:实现设备信息上报与远程控制 1. 介绍 1.1 MQTT是什么? MQTT(Message Queuing Telemetry Transport)是一种轻量级的消息传输协议,最初由IBM开发,用于连接远程设备与服务器之间的通信。它在物…...
Python爬虫——新手使用代理ip详细教程
Python代理IP爬虫是一种可以让爬虫拥有更多网络访问权限的技术。代理IP的作用是可以为爬虫提供多个IP地址,从而加快其爬取数据的速度,同时也可以避免因为访问频率过高而被网站封禁的问题。本文将介绍如何使用Python实现代理IP的爬取和使用。 一、代理IP的…...
idea VCS配置多个远程仓库
Idea VCS配置多个远程仓库 首先要有连个远程仓库地址 idea 添加数据源 查看推送记录 添加数据源 ok之后填写账号密码 推送本地项目 选择不同远程地址 push 查看不同远程地址的 不同分支的 推送记录 不期而遇的温柔: 应用开源架构进行项目开发,特别是那…...
LKPNR: LLM and KG for Personalized News Recommendation Framework
本文是LLM系列文章,针对《LKPNR: LLM and KG for Personalized News Recommendation Framework》的翻译。 LKPNR:LLM和KG的个性化新闻推荐框架 摘要1 引言2 相关工作3 问题定义4 框架5 实验6 案例7 结论 摘要 准确地向用户推荐候选新闻文章是个性化新闻推荐系统面…...
Xshell只能打开一个会话、左边栏消失不见、高级设置在哪儿、快捷键设置解决
Xshell只能打开一个会话、左边会话栏消失不见、高级设置在哪儿解决 1.问题: xshell会话(窗口)上方切换栏不见了的处理办法 解决方法:ctrl shift t 2.问题: 左边会话管理器不见了 解决方法: 3.问题…...
Android Retrofit 高级使用与原理
简介 在 Android 开发中,网络请求是一个极为关键的部分。Retrofit 作为一个强大的网络请求库,能够简化开发流程,提供高效的网络请求能力。本文将深入介绍 Retrofit 的高级使用与原理,帮助读者更全面地理解和应用这一库。 什么是…...
Unity3D开发流程及注意事项
使用Unity3D开发游戏需要遵循一定的流程和注意事项,以确保项目的顺利进行并获得良好的结果。以下是一般的游戏开发流程以及一些注意事项,希望对大家有所帮助。北京木奇移动技术有限公司,专业的软件外包开发公司,欢迎交流合作。 游…...
wordpress后台更新后 前端没变化的解决方法
使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...
ES6从入门到精通:前言
ES6简介 ES6(ECMAScript 2015)是JavaScript语言的重大更新,引入了许多新特性,包括语法糖、新数据类型、模块化支持等,显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var…...
线程同步:确保多线程程序的安全与高效!
全文目录: 开篇语前序前言第一部分:线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分:synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分ÿ…...
蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练
前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1):从基础到实战的深度解析-CSDN博客,但实际面试中,企业更关注候选人对复杂场景的应对能力(如多设备并发扫描、低功耗与高发现率的平衡)和前沿技术的…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序
一、开发准备 环境搭建: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 项目创建: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...
如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...
OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...
R语言速释制剂QBD解决方案之三
本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...
手机平板能效生态设计指令EU 2023/1670标准解读
手机平板能效生态设计指令EU 2023/1670标准解读 以下是针对欧盟《手机和平板电脑生态设计法规》(EU) 2023/1670 的核心解读,综合法规核心要求、最新修正及企业合规要点: 一、法规背景与目标 生效与强制时间 发布于2023年8月31日(OJ公报&…...
协议转换利器,profinet转ethercat网关的两大派系,各有千秋
随着工业以太网的发展,其高效、便捷、协议开放、易于冗余等诸多优点,被越来越多的工业现场所采用。西门子SIMATIC S7-1200/1500系列PLC集成有Profinet接口,具有实时性、开放性,使用TCP/IP和IT标准,符合基于工业以太网的…...
