当前位置: 首页 > news >正文

篇二十三:设计模式的综合实例:构建完整项目

篇二十三:"设计模式的综合实例:构建完整项目"

开始本篇文章之前先推荐一个好用的学习工具,AIRIght,借助于AI助手工具,学习事半功倍。欢迎访问:http://airight.fun/。

另外有2本不错的关于设计模式的资料,分享出来与大家学习参考。
链接:https://pan.baidu.com/s/1RmhQF_o1CdK8U7s5KeILog?pwd=xc6d
提取码:xc6d

在前面的文章中,我们详细介绍了各种设计模式的原理、用途和实现方式。这些设计模式都是软件开发中的重要工具,可以帮助我们解决不同的设计问题,提高代码的灵活性、可维护性和可扩展性。接下来,我们将结合前面介绍的设计模式,构建一个完整的项目,展示设计模式在实际项目中的综合应用。

1. 项目简介:

我们将构建一个简单的音乐播放器项目,该项目包含以下功能:

  • 音乐播放功能:支持播放、暂停、停止音乐。
  • 播放列表功能:支持创建、添加和删除播放列表,以及将音乐添加到播放列表中。
  • 音乐收藏功能:支持收藏喜欢的音乐,以便快速查找。

2. 使用的设计模式:

在这个项目中,我们将使用以下设计模式来解决各种设计问题:

  • 单例模式:用于创建唯一的音乐播放器实例,确保全局只有一个播放器对象。
  • 工厂方法模式:用于创建音乐播放器和播放列表对象,隐藏对象的创建细节。
  • 抽象工厂模式:用于创建不同平台下的音乐播放器和播放列表对象。
  • 建造者模式:用于逐步构造复杂的音乐播放器对象。
  • 原型模式:用于克隆音乐对象,以便在播放列表中复用音乐。
  • 适配器模式:用于让不同类型的音乐适配到播放器中。
  • 桥接模式:用于将音乐播放器和操作系统平台解耦。
  • 装饰器模式:用于动态增加音乐收藏功能。
  • 组合模式:用于构建播放列表的树形结构。
  • 外观模式:用于简化音乐播放器的操作。
  • 状态模式:用于控制音乐播放器的状态和行为。
  • 观察者模式:用于监听音乐播放状态的变化。
  • 模板方法模式:用于固定音乐播放的步骤。
  • 命令模式:用于封装音乐播放的请求。
  • 备忘录模式:用于保存音乐播放器的状态。
  • 访问者模式:用于分离音乐对象和操作算法。
  • 中介者模式:用于解耦音乐播放器和播放列表之间的交互。

3. 项目实现:

为了简化代码,我们只给出项目的伪代码示例,演示如何在项目中应用上述设计模式。在实际项目中,您需要根据具体情况进行适当的实现。

// 音乐播放器类(单例模式)
class MusicPlayer {
public:static MusicPlayer* getInstance() {// 返回唯一的音乐播放器实例}void play() {// 播放音乐}void pause() {// 暂停音乐}void stop() {// 停止音乐}
};// 抽象工厂类
class AbstractFactory {
public:virtual MusicPlayer* createMusicPlayer() = 0;virtual Playlist* createPlaylist() = 0;
};// Windows工厂类(实现抽象工厂)
class WindowsFactory : public AbstractFactory {
public:MusicPlayer* createMusicPlayer() {// 返回Windows平台下的音乐播放器对象}Playlist* createPlaylist() {// 返回Windows平台下的播放列表对象}
};// MacOS工厂类(实现抽象工厂)
class MacOSFactory : public AbstractFactory {
public:MusicPlayer* createMusicPlayer() {// 返回MacOS平台下的音乐播放器对象}Playlist* createPlaylist() {// 返回MacOS平台下的播放列表对象}
};// 播放列表类(组合模式)
class Playlist {
public:void addMusic(Music* music) {// 将音乐添加到播放列表}void removeMusic(Music* music) {// 从播放列表中删除音乐}
};// 音乐类(原型模式)
class Music {
public:virtual Music* clone() = 0;
};// MP3音乐类(继承音乐类)
class MP3Music : public Music {
public:Music* clone() {// 克隆MP3音乐对象}
};// WAV音乐类(继承音乐类)
class WAVMusic : public Music {
public:Music* clone() {// 克隆WAV音乐对象}
};// 适配器类
class MusicAdapter : public Music {
public:MusicAdapter(Music* music) : music_(music) {}Music* clone() {// 使用适配器适配音乐对象}private:Music* music_;
};// 装饰器类
class MusicDecorator : public Music {
public:MusicDecorator(Music* music) : music_(music) {}Music* clone() {// 使用装饰器装饰音乐对象}private:Music* music_;
};// 状态类
class State {
public:virtual void handle() = 0;
};// 播放状态类(实现状态类)
class PlayState : public State {
public:void handle() {// 处理播放状态的行为}
};// 暂停状态类(实现状态类)
class PauseState : public State {
public:void handle() {// 处理暂停状态的行为}
};// 上下文类
class Context {
public:void setState(State* state) {// 设置状态}void request() {// 发送请求给当前状态}private:State* state_;
};// 观察者类
class Observer {
public:virtual void update() = 0;
};// 音乐观察者类(实现观察者)
class MusicObserver : public Observer {
public:void update() {// 处理音乐播放状态的更新}
};// 模板方法类
class PlayTemplate {
public:void play() {// 固定的音乐播放步骤playStart();playMusic();playEnd();}protected:virtual void playStart() = 0;virtual void playMusic() = 0;virtual void playEnd() = 0;
};// MP3音乐播放类(继承模板方法类)
class MP3Play : public PlayTemplate {
protected:void playStart() {// MP3播放器启动}void playMusic() {// 播放MP3音乐}void playEnd() {// 播放结束}
};// 命令类
class Command {
public:virtual void execute() = 0;
};// 播放命令类(实现命令类)
class PlayCommand : public Command {
public:void execute() {// 执行播放命令}
};// 备忘录类
class Memento {
public:Memento(MusicPlayer* player) : player_(player) {}MusicPlayer* getPlayer() {return player_;}private:MusicPlayer* player_;
};// 负责人类
class Caretaker {
public:void saveState(MusicPlayer* player) {// 保存音乐播放器状态}Memento* restoreState() {// 恢复音乐播放器状态}private:Memento* memento_;
};// 访问者类
class Visitor {
public:virtual void visit(Music* music) = 0;
};// MP3访问者类(实现访问者)
class MP3Visitor : public Visitor {
public:void visit(Music* music) {// 访问MP3音乐对象}
};// 中介者类
class Mediator {
public:virtual void playMusic() = 0;virtual void stopMusic() = 0;
};// 音乐播放器类(中介者模式)
class MusicPlayer : public Mediator {
public:void playMusic() {// 播放音乐}void stopMusic() {// 停止音乐}
};

4. 总结:

在本文中,我们结合前面介绍的设计模式,构建了一个简单的音乐播放器项目。通过使用单例模式、工厂方法模式、抽象工厂模式、建造者模式、原型模式、适配器模式、桥接模式、装饰器模式、组合模式、外观模式、状态模式、观察者模式、模板方法模式、命令模式、备忘录模式、访问者模式和中介者模式,我们解决了音乐播放器项目中的不同设计问题,使项目代码更加灵活、可维护和可扩展。

设计模式是软件开发中的重要工具,通过学习和应用不同的设计模式,我们可以提高代码的质量、可读性和可维护性。在实际项目中,我们可以根据具体需求选择合适的设计模式来解决问题,让我们的项目更加健壮和高效。

希望本文对您理解设计模式的综合应用有所帮助,并激发您在日常开发中更多地运用设计模式来构建高质量的软件项目。设计模式是一门值得深入学习和探索的技术,它能够帮助我们写出优雅、高效和可维护的代码。

参考文献:

  • Gamma, E., Helm, R., Johnson, R., & Vlissides, J. (1994). Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley Professional.
  • C++ Core Guidelines: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines
  • Design Patterns in C++: https://www.oreilly.com/library/view/design-patterns-in/0201633714/

感谢您的阅读,欢迎一起探讨,共同进步,推荐大家使用学习助手AIRight来解答学习过程中的问题,访问链接:http://airight.fun/

相关文章:

篇二十三:设计模式的综合实例:构建完整项目

篇二十三:"设计模式的综合实例:构建完整项目" 开始本篇文章之前先推荐一个好用的学习工具,AIRIght,借助于AI助手工具,学习事半功倍。欢迎访问:http://airight.fun/。 另外有2本不错的关于设计模…...

FFmpeg常见命令行(三):FFmpeg转码

前言 在Android音视频开发中,网上知识点过于零碎,自学起来难度非常大,不过音视频大牛Jhuster提出了《Android 音视频从入门到提高 - 任务列表》。本文是Android音视频任务列表的其中一个, 对应的要学习的内容是:如何使…...

合宙Air724UG LuatOS-Air script lib API--scanCode

Table of Contents scanCode scanCode.request(cbFnc, timeout) scanCode 模块功能:扫码. 支持二维码、条形码扫描 scanCode.request(cbFnc, timeout) 设置扫码请求 参数 名称 传入值类型 释义 cbFnc function 扫码返回或者超时未返回的回调函数,回调…...

2023年新手如何学剪辑视频 想学视频剪辑如何入门

随着短视频、vlog等媒体形式的兴起,视频剪辑已经成为了热门技能。甚至有人说,不会修图可以,但不能不会剪视频。实际上,随着各种智能软件的发展,视频剪辑已经变得越来越简单。接下来,一起来看看新手如何学剪…...

C++的auto究竟是何方神圣

C的auto究竟是何方神圣 前言🙌auto(C 11) 的使用细则auto是什么? auto声明的变量是在什么时期被编译器推导出来呢?为什么使用auto进行定义变量时,必须进行初始化? auto 的使用场景auto与指针和引…...

网络安全【黑客】面试题汇总

前言 一眨眼2023年已经过去一大半,不知道大家有没有找到心仪的工作。作为一个安全老鸟,工作这么多年,面试过很多人也出过很多面试题目,也在网上收集了各类关于渗透面试题目,里面有我对一些问题的见解,希望…...

docker菜谱大全

记录docker常用软件安装,感谢小马哥和杨师傅的投稿。😎😎😎 相关文档: DockerHub:https://hub.docker.com/Linux手册:https://linuxcool.com/Docker文档:https://docs.docker.com/Do…...

git: git checkout命令

git checkout 命令在Git中有不同的用法和功能&#xff0c;具体取决于您在命令后面提供的参数。以下是一些常见的用法&#xff1a; 1. 切换分支&#xff1a;您可以使用 git checkout <branch> 切换到指定的分支。例如&#xff0c;要切换到名为 "feature-branch"…...

以游戏编程的角度看待模拟时间的算法题——以PAT甲级1026 Table Tennis为例

对于需要模拟时间的算法题&#xff0c;可以将开始时间作为游戏的开始&#xff08;如Unity的Start或UE的BeginPlay&#xff09;&#xff0c;每一秒的模拟作为游戏的画面更新&#xff08;如Unity的Update或UE的Tick&#xff09;&#xff0c;结束时间可作为游戏的结束&#xff08;…...

SNAT与DNAT原理

SNAT和DNAT &#xff08;源地址转换和目标地址转换&#xff09; SNAT&#xff1a;源地址转换。内网到外网转换的是源地址。 DNAT&#xff1a;目标地址转换&#xff1a;外网到内网转换的是目的地址 &#xff08;把内部服务器的ip地址转换成一个所有人都可以访问的地址&#xff0…...

04-2_Qt 5.9 C++开发指南_SpinBox使用

文章目录 1. SpinBox简介2. SpinBox使用2.1 可视化UI设计2.2 widget.h2.3 widget.cpp 1. SpinBox简介 QSpinBox 用于整数的显示和输入&#xff0c;一般显示十进制数&#xff0c;也可以显示二进制、十六进制的数&#xff0c;而且可以在显示框中增加前缀或后缀。 QDoubleSpinBox…...

接口安全防护方案

文章目录 1.认证与授权机制2.参数校验3.接口加密4.防止暴力破解5.安全头设置6.日志监控 1.认证与授权机制 使用令牌&#xff08;Token&#xff09;、OAuth等认证方式&#xff0c;确保只有合法用户可以访问接口。授权机制可以防止未经授权的用户访问敏感接口。 示例&#xff1a;…...

机器学习复习题

1 单选题 ID3算法、C4.5算法、CART算法都是&#xff08; &#xff09;研究方向的算法。 A . 决策树 B. 随机森林 C. 人工神经网络 D. 贝叶斯学习 参考答案&#xff1a;A &#xff08; &#xff09;作为机器学习重要算法之一&#xff0c;是一种利用多个树分类器进行分类和预测…...

无线液位传感器—简介

近年来&#xff0c;随着无线传感网络技术的愈发成熟和稳定&#xff0c;无线传感器因其安装、维护方便&#xff0c;不用布线、节约成本&#xff0c;监测方便&#xff0c;使用灵活&#xff0c;可适用于多种工业领域等优点&#xff0c;正在逐步替代部分传统有线传感器&#xff0c;…...

通讯协议034——全网独有的OPC HDA知识一之聚合(三)时间加权平均

本文简单介绍OPC HDA规范的基本概念&#xff0c;更多通信资源请登录网信智汇(wangxinzhihui.com)。 本节旨在详细说明HDA聚合的要求和性能。其目的是使HDA聚合标准化&#xff0c;以便HDA客户端能够可靠地预测聚合计算的结果并理解其含义。如果用户需要聚合中的自定义功能&…...

Android 13 Hotseat定制化修改——003 hotseat图标大小修改

目录 一.背景 二.未修改前效果 三.修改后效果 一.背景 由于需求是需要自定义修改Hotseat,所以此篇文章是记录如何自定义修改hotseat的,应该可以覆盖大部分场景,修改点有修改hotseat布局方向,hotseat图标数量,hotseat图标大小,hotseat布局位置,hotseat图标禁止形成文件…...

21、springboot的宽松绑定及属性处理类的构造注入

springboot的宽松绑定及属性处理类的构造注入 ★ 如何使用属性处理类所读取的属性 属性处理类最终变成了Spring容器中的一个Bean组件&#xff0c;因此接下来Spring即可将该Bean组件注入任意其他组件。 这种做法的好处是&#xff1a;可以将大量的配置信息封装一个对象——所以…...

nginx负载均衡(反向代理)

nginx负载均衡 负载均衡&#xff1a;由反向代理来实现。 nginx的七层代理和四层代理&#xff1a; 七层是最常用的反向代理方式&#xff0c;只能配置在nginx配置文件的http模块当中&#xff0c;而且配置方法名称&#xff1a;upstream模块&#xff0c;不能写在server模块中&#…...

AWS上传私有windows server2019镜像64位

一.制作自己的镜像 我使用的是esxi&#xff0c;建立一个windows虚拟机&#xff0c;开启。 根据aws官方文档&#xff0c;虚拟机里的系统重要需要注意以下几点&#xff1a; 1.只有一张网卡&#xff0c;ip获取配置成dhcp。 2.关闭系统防火墙。 3.开启windows rdp 远程功能。 …...

查看当前仓库对应的远程仓库地址

查看当前仓库对应的远程仓库地址 git remote -v这条命令能显示你当前仓库中已经添加了的仓库名和对应的仓库地址&#xff0c;通常来讲&#xff0c;会有两条一模一样的记录&#xff0c;分别是fetch和push&#xff0c;其中fetch是用来从远程同步 push是用来推送到远程 修改仓库…...

shell脚本--常见案例

1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件&#xff1a; 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例

文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

spring:实例工厂方法获取bean

spring处理使用静态工厂方法获取bean实例&#xff0c;也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下&#xff1a; 定义实例工厂类&#xff08;Java代码&#xff09;&#xff0c;定义实例工厂&#xff08;xml&#xff09;&#xff0c;定义调用实例工厂&#xff…...

04-初识css

一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...

GitHub 趋势日报 (2025年06月08日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...

uniapp中使用aixos 报错

问题&#xff1a; 在uniapp中使用aixos&#xff0c;运行后报如下错误&#xff1a; AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...

Python 训练营打卡 Day 47

注意力热力图可视化 在day 46代码的基础上&#xff0c;对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...

Copilot for Xcode (iOS的 AI辅助编程)

Copilot for Xcode 简介Copilot下载与安装 体验环境要求下载最新的安装包安装登录系统权限设置 AI辅助编程生成注释代码补全简单需求代码生成辅助编程行间代码生成注释联想 代码生成 总结 简介 尝试使用了Copilot&#xff0c;它能根据上下文补全代码&#xff0c;快速生成常用…...

SpringCloud优势

目录 完善的微服务支持 高可用性和容错性 灵活的配置管理 强大的服务网关 分布式追踪能力 丰富的社区生态 易于与其他技术栈集成 完善的微服务支持 Spring Cloud 提供了一整套工具和组件来支持微服务架构的开发,包括服务注册与发现、负载均衡、断路器、配置管理等功能…...

Spring是如何实现无代理对象的循环依赖

无代理对象的循环依赖 什么是循环依赖解决方案实现方式测试验证 引入代理对象的影响创建代理对象问题分析 源码见&#xff1a;mini-spring 什么是循环依赖 循环依赖是指在对象创建过程中&#xff0c;两个或多个对象相互依赖&#xff0c;导致创建过程陷入死循环。以下通过一个简…...