面向对象与设计模式第二节:设计模式实战

第三章:面向对象与设计模式

第二节:设计模式实战

设计模式是软件工程中的一项重要实践,它为解决常见的设计问题提供了经过验证的解决方案。本课将深入探讨几种常见的设计模式,并通过实际案例分析其在项目中的应用。

1. 每种设计模式的详尽解释与代码示例

设计模式分为三大类:创建型模式、结构型模式和行为型模式。以下是每种模式的详细解释与代码示例。

1.1 创建型模式

创建型模式专注于对象的创建过程,提供了创建对象的多种方式,降低了系统的复杂度。

1.1.1 单例模式

单例模式确保某个类仅有一个实例,并提供一个全局访问点。它非常适合于需要全局访问的对象,如配置管理器或数据库连接。

实现步骤

  1. 将构造函数设为私有。
  2. 提供一个静态方法,用于获取单例实例。
  3. 在静态方法中检查实例是否存在,如果不存在,则创建一个。

代码示例

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 工厂模式

工厂模式定义了一个接口,用于创建对象,但将具体实现推迟到子类中。它提供了一种封装对象创建的方式,使得客户端不需要了解具体的创建过程。

实现步骤

  1. 定义一个产品接口。
  2. 创建具体的产品类实现该接口。
  3. 定义一个工厂类,用于创建具体产品的实例。

代码示例

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 适配器模式

适配器模式允许将一个类的接口转换成客户端所期望的另一种接口,使得不兼容的接口能够协同工作。

实现步骤

  1. 定义目标接口。
  2. 实现适配器类,内部持有被适配者的实例。
  3. 在适配器类中实现目标接口的方法,调用被适配者的方法。

代码示例

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 装饰者模式

装饰者模式允许动态地给一个对象添加一些额外的职责,提供比继承更灵活的扩展方式。

实现步骤

  1. 定义一个组件接口。
  2. 创建具体的组件类实现该接口。
  3. 创建装饰者类,持有一个组件实例,并在其方法中添加功能。

代码示例

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 策略模式

策略模式定义了一系列算法,并将每一个算法封装起来,使它们可以互换使用。

实现步骤

  1. 定义一个策略接口。
  2. 实现多个具体策略类。
  3. 定义上下文类,持有一个策略实例,并在运行时根据需要选择策略。

代码示例

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 测试与验证

重构完成后,运行测试用例验证系统的正确性。通过测试,确保新引入的设计模式未破坏现有功能。

总结

本课详细分析了多种设计模式及其在实际项目中的应用,强调了设计模式在提高代码质量和可维护性方面的重要性。通过掌握设计模式,开发者可以在设计和重构代码时,做出更为明智的决策。

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

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

相关文章

JavaEE初阶---文件IO总结

文章目录 1.文件初识2.java针对于文件的操作2.1文件系统的操作---file类2.2文件内容的操作---流对象的分类2.4字符流的操作》文本文件2.4.1异常的说明2.4.2第一种文件内容的读取方式2.4.3第二种读取方式2.4.4close的方法的介绍2.4.5close的使用优化操作2.4.6内容的写入 2.3字节…

无需依赖闭源模型!司南CompassJudger为AI评测带来新选择

前沿科技速递&#x1f680; 近期&#xff0c;司南OpenCompass团队发布了一款开源的全能评价模型——CompassJudger。这是全球首个全能开源的 All-in-one Judge Model&#xff0c;不仅支持主流的双向对比&#xff08;pair-wise&#xff09;和单向评分&#xff08;point-wise&…

软件工程--需求分析与用例模型

面向对象分析(ObjectOrientedAnalysis&#xff0c;简称OOA) 分析和理解问题域&#xff0c;找出描述问题域所需的类和对象&#xff0c;分析它们的内部构成和外部关系&#xff0c;建立独立于实现的OOA模型&#xff0c;暂时忽略与系统实现有关的问题。 主要使用UML中的以下几种图…

全球知名度最高的华人起名大师颜廷利:世界顶级思想哲学教育家

全国给孩子起名最好的大师颜廷利教授在其最新的哲学探索中&#xff0c;提出了《升命学说》这一前沿理论观点&#xff0c;该理论不仅深刻地回应了古今中外众多哲学流派和思想体系的精髓&#xff0c;还巧妙地融合了实用主义、理想主义以及经验主义的核心理念。通过这一独特的视角…

我准备写一份Stable Diffusion入门指南-part1

我准备写个SD自学指南&#xff0c;当然也是第一次写&#xff0c;可能有点凌乱&#xff0c;后续我会持续更新不断优化&#xff0c;我是生产队的驴&#xff0c;欢迎监督。 Stable Diffusion WebUI 入门指南 Stable Diffusion WebUI 是一款基于 Stable Diffusion 模型的用户界面…

力扣 中等 740.删除并获得点数

文章目录 题目介绍题解 题目介绍 题解 由题意可知&#xff0c;在选择了数组中元素 a 后&#xff0c;该元素以及所有等于 a−1 和 a1 的元素都会从数组中删去&#xff0c;并获得 a 的点数。若还有多个值为 a的元素&#xff0c;由于所有等于 a−1 或 a1 的元素已经被删除&#x…

三种材料的金相图及金相图解析材料

3. 二&#xff0e;不同温度下三种材料&#xff08;铸铁&#xff0c;铝&#xff0c;低碳钢&#xff09;的低温脆性&#xff0c;相关材料&#xff0c;文献引用 三&#xff0e;三种材料在汽车制造中可能的应用 &#xff08;如捷豹用铝合金降低车身重量&#xff09;.三种材料哪个材…

Linux: Shell编程入门

Shell 编程入门 1 ) Shell 概念 shell 是 在英语中 壳, 外壳的意思可以把它想象成嵌入在linux这样的操作系统里面的一个微型的编程语言不像C语言, C 或 Java 等编程语言那么完整&#xff0c;它可以帮我们完成很多自动化任务例如保存数据监测系统的负载等等&#xff0c;我们同样…

AI博士人手10篇顶会,遭质疑。。。

B站&#xff1a;啥都会一点的研究生公众号&#xff1a;啥都会一点的研究生 AI科技圈又发生了啥新鲜事&#xff1f; “稚晖君”灵犀X1全球开源&#xff0c;推动人形机器人技术共享 智元机器人宣布其人形机器人灵犀X1正式面向全球开源&#xff0c;提供了超过1.2GB的软硬件全套…

【LeetCode】11.盛最多水的容器

思路&#xff1a; 利用双指针法进行移动&#xff0c;一个在头一个在尾&#xff0c;此时宽度最宽&#xff0c;当宽度缩小时&#xff0c;高度发生变化&#xff0c;从而可以找到最大值。 代码&#xff1a; int maxArea(int* height, int heightSize) {int* left height;int* …

android——渐变色

1、xml的方式实现渐变色 效果图&#xff1a; xml的代码&#xff1a; <?xml version"1.0" encoding"utf-8"?> <shape xmlns:android"http://schemas.android.com/apk/res/android"xmlns:tools"http://schemas.android.com/tools…

Java常见数据结构

数组 数组的特性存储空间是连续的长度是不可变的只能存储 相同的类型(不严谨)可以通过下标访问数组的内容 a[10] 复杂度是O1每个元素的默认是为零值 0 null false -> 一个对象的基本的数据域的初始化也是这样的 Student 类中的username属性 默认值 链表 查找麻烦 插入和删…

logback日志导入使用

1导入配置 <!-- 日志 &#xff0c; 会自动传递slf4j门面--> <dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.3</version> </dependency>2 引入配置 Logback要求…

开源实时数仓的构建

设计计思路 基本思路 开源数据平台的设计思路是通过 Flink SQL Batch、StartRocks SQL 、StartRocks物化视图 的能力实现一个离线任务的开发&#xff1b;使用 DolphinScheduler 进行离线工作流编排和调度&#xff1b;通过 Flink CDC 和 Flink SQL 实现流处理能力&#xff0c;进…

HarmonyOS 相对布局(RelativeContainer)

1. HarmonyOS 相对布局&#xff08;RelativeContainer&#xff09; 文档中心:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/arkts-layout-development-relative-layout-V5   RelativeContainer为采用相对布局的容器&#xff0c;支持容器内部的子元素设…

【C++】—— 模板进阶

【C】—— 模板进阶 1 非类型模板参数1.1 什么是非类型模板参数1.2 非类型模板参数对比宏的优势1.3 array 简单了解 2 模板的特化2.1 引子2.2 函数模板特化2.3 函数模板特化的坑2.4 类模板的特化2.4.1 全特化2.4.2 偏特化&#xff08;半特化&#xff09;2.4.3 选择2.4.4 偏特化…

英伟达GPU算力【自用】

GPU&#xff08;图形处理单元&#xff09;算力的提升是驱动当代科技革命的核心力量之一&#xff0c;尤其在人工智能、深度学习、科学计算和超级计算机领域展现出了前所未有的影响力。2024年的GPU技术发展&#xff0c;不仅体现在游戏和图形处理的传统优势上&#xff0c;更在跨行…

unity项目导出安卓工程后,在AndroidStudio打包报错:unityLibrary:BuildIl2CppTask‘.

下面这个是我在unity开发者社区提问后&#xff0c;他们回答得&#xff1a; 解决方案&#xff1a;我这边按照这几个方案检查了下&#xff0c;NDK和JDK都没问题&#xff0c;最后重启电脑才解决的&#xff0c;应该是文件被锁定了&#xff0c;我用的windows系统的。 验证&#xff…

书生第四期作业:L0G1000 任务作业

永不止步&#xff0c;空杯心态&#xff0c;从零开始&#xff0c;复习一下&#xff0c;争取完成全部任务 SSH登录 PowerShell命令行登录成功 VScode SSH登录成功 进入root文件夹 闯关任务&#xff1a;映射运行hello_world.py 可选任务1&#xff1a;linux命令行基本命令过一边 …

【WPF】中Dispatcher的DispatcherPriority参数使用

在 WPF 中&#xff0c;DispatcherPriority 参数用于指定通过 Dispatcher 调度的操作的执行优先级。加入 DispatcherPriority 参数的情况通常取决于你希望操作何时以及如何被执行。 1.Dispatcher的DispatcherPriority参数使用 以下是几种情况和示例说明&#xff1a; 1.1 需要…