面向对象与设计模式第二课:设计模式实战
第三章:面向对象与设计模式
第二课:设计模式实战
设计模式是软件工程中的一项重要实践,它为解决常见的设计问题提供了经过验证的解决方案。本课将深入探讨几种常见的设计模式,并通过实际案例分析其在项目中的应用。
1. 每种设计模式的详尽解释与代码示例
设计模式分为三大类:创建型模式、结构型模式和行为型模式。以下是每种模式的详细解释与代码示例。
1.1 创建型模式
创建型模式专注于对象的创建过程,提供了创建对象的多种方式,降低了系统的复杂度。
1.1.1 单例模式
单例模式确保某个类仅有一个实例,并提供一个全局访问点。它非常适合于需要全局访问的对象,如配置管理器或数据库连接。
实现步骤:
- 将构造函数设为私有。
- 提供一个静态方法,用于获取单例实例。
- 在静态方法中检查实例是否存在,如果不存在,则创建一个。
代码示例:
class Singleton {
private:static Singleton* instance;// 私有构造函数,防止外部创建实例Singleton() {}public:static Singleton* getInstance() {if (!instance) {instance = new Singleton();}return instance;}void showMessage() {std::cout << "Hello from Singleton!" << std::endl;}
};// 初始化静态成员
Singleton* Singleton::instance = nullptr;
使用场景:
- 在应用程序中需要唯一实例的地方,例如日志记录、配置管理。
优缺点:
- 优点:控制实例数量,减少内存开销。
- 缺点:可能导致全局状态的问题,不利于单元测试。
实际应用: 在大型企业应用中,单例模式被广泛用于数据库连接池的管理,确保应用程序中的数据库连接都是通过一个管理实例来处理,从而提高资源的利用率和降低并发访问的问题。
扩展讨论: 为了确保线程安全,可以使用懒汉式或饿汉式的单例实现方法,或者使用std::call_once
来确保线程安全的实例创建。
1.1.2 工厂模式
工厂模式定义了一个接口,用于创建对象,但将具体实现推迟到子类中。它提供了一种封装对象创建的方式,使得客户端不需要了解具体的创建过程。
实现步骤:
- 定义一个产品接口。
- 创建具体的产品类实现该接口。
- 定义一个工厂类,用于创建具体产品的实例。
代码示例:
class Product {
public:virtual void use() = 0;
};class ConcreteProductA : public Product {
public:void use() override {std::cout << "Using Product A" << std::endl;}
};class ConcreteProductB : public Product {
public:void use() override {std::cout << "Using Product B" << std::endl;}
};class Creator {
public:virtual Product* factoryMethod() = 0;void someOperation() {Product* product = factoryMethod();product->use();}
};class ConcreteCreatorA : public Creator {
public:Product* factoryMethod() override {return new ConcreteProductA();}
};class ConcreteCreatorB : public Creator {
public:Product* factoryMethod() override {return new ConcreteProductB();}
};
使用场景:
- 在创建对象时,客户端无需知道具体的类,只需调用工厂方法。
优缺点:
- 优点:代码解耦,易于扩展。
- 缺点:增加了系统的复杂度。
实际应用: 在电商平台中,不同的支付方式(如信用卡、PayPal)可以使用工厂模式创建,使得添加新支付方式时,只需新增一个工厂类,而无需更改客户端代码。
扩展讨论: 工厂模式的变种,如抽象工厂模式,允许创建多个系列的产品,适用于复杂的对象创建场景。
1.2 结构型模式
结构型模式关注类和对象的组合,以形成更大的结构,常用的有适配器模式、装饰者模式等。
1.2.1 适配器模式
适配器模式允许将一个类的接口转换成客户端所期望的另一种接口,使得不兼容的接口能够协同工作。
实现步骤:
- 定义目标接口。
- 实现适配器类,内部持有被适配者的实例。
- 在适配器类中实现目标接口的方法,调用被适配者的方法。
代码示例:
class Target {
public:virtual void request() {std::cout << "Target request" << std::endl;}
};class Adaptee {
public:void specificRequest() {std::cout << "Specific request" << std::endl;}
};class Adapter : public Target {
private:Adaptee* adaptee;public:Adapter(Adaptee* a) : adaptee(a) {}void request() override {adaptee->specificRequest();}
};
使用场景:
- 当需要集成已有系统而无法修改其代码时,例如引入第三方库。
优缺点:
- 优点:提高了系统的灵活性。
- 缺点:增加了类的数量,可能导致系统复杂性提高。
实际应用: 在项目中,如果需要集成不同的第三方库(如支付接口),适配器模式可以帮助统一接口,使得调用方式一致,便于后期维护和更换。
扩展讨论: 适配器模式可以与装饰者模式结合使用,以同时实现接口适配和功能增强。
1.2.2 装饰者模式
装饰者模式允许动态地给一个对象添加一些额外的职责,提供比继承更灵活的扩展方式。
实现步骤:
- 定义一个组件接口。
- 创建具体的组件类实现该接口。
- 创建装饰者类,持有一个组件实例,并在其方法中添加功能。
代码示例:
class Component {
public:virtual std::string operation() {return "Base Component";}
};class Decorator : public Component {
protected:Component* component;public:Decorator(Component* c) : component(c) {}std::string operation() override {return component->operation() + " + Decorated";}
};
使用场景:
- 需要在运行时添加功能时,例如用户界面元素的动态装饰。
优缺点:
- 优点:增强了系统的灵活性和可扩展性。
- 缺点:增加了复杂度,可能导致过多的小类。
实际应用: 在GUI框架中,可以使用装饰者模式为按钮添加边框、阴影等效果,而无需创建多个子类。
扩展讨论: 装饰者模式与策略模式的结合可以实现功能的多样化,通过不同的装饰组合,产生不同的行为。
1.3 行为型模式
行为型模式主要关注对象之间的交互和职责分配,常见的有策略模式、观察者模式等。
1.3.1 策略模式
策略模式定义了一系列算法,并将每一个算法封装起来,使它们可以互换使用。
实现步骤:
- 定义一个策略接口。
- 实现多个具体策略类。
- 定义上下文类,持有一个策略实例,并在运行时根据需要选择策略。
代码示例:
class Strategy {
public:virtual void algorithm() = 0;
};class ConcreteStrategyA : public Strategy {
public:void algorithm() override {std::cout << "Algorithm A" << std::endl;}
};class ConcreteStrategyB : public Strategy {
public:void algorithm() override {std::cout << "Algorithm B" << std::endl;}
};class Context {
private:Strategy* strategy;public:Context(Strategy* s) : strategy(s) {}void executeStrategy() {strategy->algorithm();}
};
使用场景:
- 需要在运行时选择算法的情况,例如排序算法、压缩算法。
优缺点:
- 优点:提高了代码的灵活性和可扩展性。
- 缺点:客户端必须了解所有策略的类。
实际应用: 在图像处理应用中,可以根据用户的选择使用不同的图像压缩算法,而无需修改核心业务逻辑。
扩展讨论: 策略模式可以与工厂模式结合使用,根据不同条件动态选择策略。
2. 实际项目中的设计模式应用案例
通过具体项目的分析,进一步了解设计模式如何提高代码质量和开发效率。
2.1 电子商务平台中的应用
在电子商务平台中,设计模式可以帮助解决复杂的业务需求,提高代码的可维护性。
- 使用单例模式:保证配置管理和数据库连接的唯一性。
- 使用工厂模式:根据用户的选择创建不同的支付方式。
- 使用策略模式:根据用户的身份(如普通用户、VIP用户)提供不同的折扣策略。
2.2 游戏开发中的应用
在游戏开发中,设计模式的应用同样重要,能够有效管理复杂的游戏逻辑。
- 使用观察者模式:实现游戏中的事件系统,允许多个对象响应游戏事件。
- 使用状态模式:管理角色的不同状态(如行走、攻击、休息),使得状态之间的转换清晰可控。
2.3 企业级应用中的应用
在大型企业应用中,设计模式可以帮助应对日益复杂的业务需求。
- 使用适配器模式:集成不同的外部API,提供统一的接口。
- 使用装饰者模式:动态地给业务对象添加功能,例如为报告生成器添加过滤器。
3. 设计模式与代码重构的结合
设计模式不仅仅是解决问题的工具,更是进行代码重构的重要手段。通过将设计模式引入现有代码,可以提升代码的结构和可读性。
3.1 识别重构的必要性
在代码重构之前,首先需要识别出代码中的“坏味道”,例如:
- 过长的函数。
- 重复代码。
- 难以理解的类设计。
3.2 引入设计模式
在进行重构时,可以考虑引入适合的设计模式来优化代码结构。对于每个“坏味道”,选择合适的模式进行修复。例如:
- 对于重复代码,可以考虑使用模板方法模式。
- 对于过长的函数,可以使用策略模式,将逻辑拆分为不同的策略。
3.3 重构过程
实施重构时,应确保每个修改都有相关的单元测试,以避免引入新问题。重构应遵循小步快跑的原则,每次只进行小幅修改,确保系统稳定性。
3.4 测试与验证
重构完成后,运行测试用例验证系统的正确性。通过测试,确保新引入的设计模式未破坏现有功能。
总结
本课详细分析了多种设计模式及其在实际项目中的应用,强调了设计模式在提高代码质量和可维护性方面的重要性。通过掌握设计模式,开发者可以在设计和重构代码时,做出更为明智的决策。
相关文章:

面向对象与设计模式第二课:设计模式实战
第三章:面向对象与设计模式 第二课:设计模式实战 设计模式是软件工程中的一项重要实践,它为解决常见的设计问题提供了经过验证的解决方案。本课将深入探讨几种常见的设计模式,并通过实际案例分析其在项目中的应用。 1. 每种设计…...

非科班出身如何转行程序员?
非科班出身是指那些大学专业为非计算机相关专业的人群,多数人对于计算机基础了解比较少,甚至零基础。这部分人群中有相当多一部分处于对于编程的兴趣和外界了解的印象想转行成为一名程序员。 非科班出身与计算机科班出身相比有着天然的劣势,在…...
多台NFS客户端访问一台nfs服务器
目录 1.安装服务 2.创建用户和用户组 3.写配置文件 (服务端) 4.创建/share目录 5.挂载服务(在两个服务端上) 6.测试 1.安装服务 yum -y install rpcbind nfs 2.创建用户和用户组 useradd -u 555 nfs-share groupadd -u 556 nfs-share …...

【STM32 HAL库】MPU6050姿态解算 卡尔曼滤波
【STM32 HAL库】MPU6050姿态解算 卡尔曼滤波 前言MPU6050寄存器代码详解mpu6050.cmpu6050.h 使用说明 前言 本篇文章基于卡尔曼滤波的原理详解与公式推导,来详细的解释下如何使用卡尔曼滤波来解算MPU6050的姿态 参考资料:Github_mpu6050 MPU6050寄存器…...

Linux系统——ssh远程连接
Linux系统——ssh远程连接 一、ssh协议介绍1、远程连接协议2、ssh服务基本操作3、ssh常用操作 二、ssh加密1、加密算法类型2、对称加密算法3、非对称加密算法 三、免密ssh的配置1、ssh认证方式2、配置免密ssh3、ssh-copy-id做了什么? 四、ssh服务配置 一、ssh协议介…...

python学习-第一个小游戏(vscode环境)
学习小甲鱼的视频,写了一个小游戏,vscode环境 运行结果 源码地址: python小游戏-猜数字源码...
程序设计基础I-单元测试2(机测)
7-1 sdut-C语言实验-AB for Input-Output Practice (不确定次数循环) Your task is to Calculate a b. Too easy?! Of course! I specially designed the problem for all beginners. You must have found that some problems have the same titles with this one, yes, a…...

Claude 3.5深夜觉醒,学会模仿人类用电脑,力压GPT-4o
1.Claude 3.5深夜重磅更新 Anthropic AI深夜发布了备受期待的Claude 3.5系列更新,包括了全新升级的Claude 3.5 Sonnet和首发的Claude 3.5 Haiku。 虽然备受期待的Opus版本尚未公布,但新版本的Sonnet在推理能力上取得了显著的进步,超越了Open…...
PuTTY
PuTTY 是一个免费的开源终端仿真器和串口终端,广泛用于在 Windows 系统上进行 SSH、Telnet 和 Rlogin 等网络协议的连接。 它允许用户通过安全的方式访问远程计算机,常用于管理服务器和网络设备。 PuTTY 也支持公钥身份验证和端口转发等功能,…...

2024软件测试面试秘籍(含答案+文档)
🍅 点击文末小卡片,免费获取软件测试全套资料,资料在手,涨薪更快 Part1 1、你的测试职业发展是什么? 测试经验越多,测试能力越高。所以我的职业发展是需要时间积累的,一步步向着高级测试工程师…...
券商api怎么获取,如何获取券商API接口?
炒股自动化:申请官方API接口,散户也可以 python炒股自动化(0),申请券商API接口 python炒股自动化(1),量化交易接口区别 Python炒股自动化(2):获取…...

跟着六西格玛设计DFSS走,让你的项目、服务、产品都“牛”起来——张驰咨询
六西格玛设计,这一数据驱动的质量管理策略,正以其独特的魅力和广泛的适用性,在各行各业中掀起了一场质量革命。从精密的制造业到细致的服务业,再到复杂的项目管理,六西格玛设计以其严谨的逻辑和高效的方法,…...

【2024.10.22练习】机器人塔
题目描述 题目分析 由于数据小,直接考虑DFS搜索底层所有排列组合。 我的代码 需要注意:这个数据有点漏洞的是题干声明NM<231,但实际上有个测试点是等于231的。 一开始在build_tower()函数中建完整个塔再判定是否…...

酒店预订订房小程序源码系统 多酒店入驻+打造类似美团的酒店模式 带完整的安装代码包以及搭建部署教程
系统概述 随着移动互联网的普及,小程序因其轻量级、无需下载安装、即用即走的特点,迅速成为各行业的标配。对于酒店预订行业而言,小程序不仅能够有效提升用户体验,还能降低运营成本,提高转化率。本源码系统正是基于这…...

springboot037基于SpringBoot的墙绘产品展示交易平台的设计与实现(论文+源码)_kaic
毕 业 设 计(论 文) 题目:墙绘产品展示交易平台设计与实现 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本墙绘产品展示…...

YOLOv8实战人脸-口罩检测与识别【数据集+YOLOv8模型+源码+PyQt5界面】
本文采用YOLOv8作为核心算法框架,结合PyQt5构建用户界面,使用Python3进行开发。YOLOv8以其高效的实时检测能力,在多个目标检测任务中展现出卓越性能。本研究针对人脸-口罩数据集进行训练和优化,该数据集包含丰富的人脸-口罩图像样…...

《黑神话悟空》各章节boss顺序汇总
第一章BOSS顺序: 1、牯护院:犀牛精,位于苍狼岭娟,击败后能获得定身术。 2、广智:火刀狼, 位于观音禅院,击败后获得广智变身,记得敲钟。 3、蓝皮幽魂:蓝皮大头࿰…...
rust中cargo.toml详细介绍
1. cargo.toml介绍 Cargo.toml是 Rust 项目的配置文件,它使用 TOML(Tom’s Obvious, Minimal Language)格式。 1.1 基本结构 [package]:包含项目的基本信息。 name:项目名称。version:项目版本号。edition:Rust 版本,如 2018、2021 等。[package]name = "abc&q…...

jupyter notebook 笔记
nbclassic 经典版 新版的 jupyter notebook 太丑了。 最难受的是字体太小了。 我还是喜欢老版本的 jupyter notebook. 安装经典版: pip install nbclassic 启动经典版: jupyter server 或是 jupyter nbclassic 参考来源: https://github.com/jupyter/nbclassic jupyter note…...

Atlas800昇腾服务器(型号:3000)—CANN安装(二)
服务器配置如下: CPU/NPU:鲲鹏 CPU(ARM64)A300I pro推理卡 系统:Kylin V10 SP1【下载链接】【安装链接】 驱动与固件版本版本: Ascend-hdk-310p-npu-driver_23.0.1_linux-aarch64.run【下载链接】 Ascend-…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...

零基础设计模式——行为型模式 - 责任链模式
第四部分:行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习!行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想:使多个对象都有机会处…...

智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制
在数字化浪潮席卷全球的今天,数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具,在大规模数据获取中发挥着关键作用。然而,传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时,常出现数据质…...

【网络安全】开源系统getshell漏洞挖掘
审计过程: 在入口文件admin/index.php中: 用户可以通过m,c,a等参数控制加载的文件和方法,在app/system/entrance.php中存在重点代码: 当M_TYPE system并且M_MODULE include时,会设置常量PATH_OWN_FILE为PATH_APP.M_T…...

C# 表达式和运算符(求值顺序)
求值顺序 表达式可以由许多嵌套的子表达式构成。子表达式的求值顺序可以使表达式的最终值发生 变化。 例如,已知表达式3*52,依照子表达式的求值顺序,有两种可能的结果,如图9-3所示。 如果乘法先执行,结果是17。如果5…...

PHP 8.5 即将发布:管道操作符、强力调试
前不久,PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5!作为 PHP 语言的又一次重要迭代,PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是,借助强大的本地开发环境 ServBay&am…...
Spring Boot + MyBatis 集成支付宝支付流程
Spring Boot MyBatis 集成支付宝支付流程 核心流程 商户系统生成订单调用支付宝创建预支付订单用户跳转支付宝完成支付支付宝异步通知支付结果商户处理支付结果更新订单状态支付宝同步跳转回商户页面 代码实现示例(电脑网站支付) 1. 添加依赖 <!…...
多元隐函数 偏导公式
我们来推导隐函数 z z ( x , y ) z z(x, y) zz(x,y) 的偏导公式,给定一个隐函数关系: F ( x , y , z ( x , y ) ) 0 F(x, y, z(x, y)) 0 F(x,y,z(x,y))0 🧠 目标: 求 ∂ z ∂ x \frac{\partial z}{\partial x} ∂x∂z、 …...
命令行关闭Windows防火墙
命令行关闭Windows防火墙 引言一、防火墙:被低估的"智能安检员"二、优先尝试!90%问题无需关闭防火墙方案1:程序白名单(解决软件误拦截)方案2:开放特定端口(解决网游/开发端口不通)三、命令行极速关闭方案方法一:PowerShell(推荐Win10/11)方法二:CMD命令…...