Qt C++设计模式->享元模式

ops/2024/10/21 10:04:33/

享元模式(Flyweight Pattern)是一种结构型设计模式,旨在通过共享相同对象来减少内存使用,尤其适合在大量重复对象的情况下。它通过将对象的可共享部分抽取出来,并在多个上下文中共享,从而避免对象的多次创建。

享元模式的应用场景

享元模式常用于减少内存开销,特别是在系统中存在大量细粒度对象时。例如,在图形界面中,大量按钮、图标等UI组件可能具有相同的外观,只需要少量的内部状态不同,这时候可以用享元模式共享相同的外观。其他应用场景包括字符处理系统、游戏中的对象管理(如子弹、树木等重复的对象),以及数据库连接池等。

享元模式的核心思想

享元模式将对象的状态分为两类:

  • 内在状态:可以共享的、不随外部环境变化的状态。

  • 外在状态:不可以共享的、随外部环境变化的状态,由客户端传入。

通过将内在状态共享,并由外部提供外在状态,享元模式大大减少了内存的占用。

享元模式示例代码

假设你正在开发一款绘图软件,需要在屏幕上绘制大量形状,如圆形。每个圆形有相同的颜色和大小,但它们的位置不同。使用享元模式可以减少内存开销,因为我们可以共享相同的圆形对象,只改变它们的位置。

#include <QDebug>
#include <QString>
#include <QHash>// 享元类:表示共享的圆形对象
class Circle {
private:QString color;  // 内在状态(可以共享的部分)int radius;     // 内在状态(可以共享的部分)public:Circle(const QString& color, int radius) : color(color), radius(radius) {}void draw(int x, int y) const {qDebug() << "Drawing circle with color" << color << "radius" << radius << "at position" << x << "," << y;}
};// 享元工厂:用于管理和提供享元对象
class CircleFactory {
private:QHash<QString, Circle*> circleMap;  // 存储已创建的享元对象public:Circle* getCircle(const QString& color, int radius) {QString key = color + QString::number(radius);// 如果共享对象已存在,则返回它if (circleMap.contains(key)) {return circleMap[key];}// 否则创建新的享元对象并存储起来Circle* newCircle = new Circle(color, radius);circleMap.insert(key, newCircle);return newCircle;}~CircleFactory() {// 清理内存for (auto circle : circleMap) {delete circle;}}
};// 使用示例
int main() {CircleFactory* factory = new CircleFactory();// 获取共享的圆形对象,并在不同位置绘制Circle* redCircle = factory->getCircle("Red", 10);redCircle->draw(10, 20);Circle* redCircle2 = factory->getCircle("Red", 10);  // 获取相同颜色和半径的圆形,应该复用上面的对象redCircle2->draw(30, 40);Circle* blueCircle = factory->getCircle("Blue", 15);blueCircle->draw(50, 60);// 清理内存delete factory;return 0;
}

代码解析

  • Circle类:享元类,表示可以共享的圆形对象。它包含内在状态(颜色和半径),这些状态可以在多个圆形对象中共享。

  • CircleFactory类:享元工厂,负责管理和提供共享的圆形对象。它通过一个哈希表(circleMap)来存储已经创建的享元对象。如果请求的对象已经存在,直接返回它;否则创建新的对象并存储起来。

  • 客户端代码:客户端通过CircleFactory获取享元对象,并为不同的外在状态(位置)进行绘制。相同的圆形对象只会创建一次。

享元模式的优点

  • 节省内存享元模式通过共享相同的对象,减少了系统中重复对象的数量,从而降低了内存使用。

  • 提高性能:通过减少对象的创建,享元模式可以提高系统的运行效率,特别是在大量重复对象的情况下。

享元模式的缺点

  • 增加复杂性享元模式要求将对象的内在状态和外在状态分离,这会增加系统的设计复杂性,尤其是在无法明确区分这两者时。

  • 管理外在状态:外在状态由客户端负责传递,因此客户端必须正确管理这些状态,否则容易导致混乱。

适合使用享元模式的情况

  • 大量细粒度对象的场景:如果系统中需要创建大量对象,且这些对象存在相同的状态,享元模式可以帮助减少内存使用。

  • 对象的大部分状态可以共享:当对象的多数属性可以在多个实例间共享时,可以使用享元模式来优化性能。

  • 性能瓶颈集中在内存占用:如果系统因为大量对象的创建导致内存消耗过高,享元模式是很好的解决方案。

享元模式与其他模式的区别

  • 与单例模式的区别:单例模式确保某个类只有一个实例,而享元模式则通过共享对象来减少内存占用,它可以创建多个实例,但这些实例具有相同的内在状态。

  • 与原型模式的区别:原型模式通过复制已有的对象来生成新对象,而享元模式则通过共享现有的对象来减少对象的数量。

Qt中的享元模式应用

在Qt开发中,享元模式可以用于共享大量的UI组件、图形对象或资源。例如,许多图标在不同地方使用相同的图形,可以通过享元模式来减少内存使用。此外,Qt中的字体管理、样式表等机制也可以借鉴享元模式的思想,避免重复加载相同的资源。

享元模式在优化系统性能和减少内存使用方面非常有效,特别是在需要创建大量细粒度对象的场景中。


http://www.ppmy.cn/ops/118356.html

相关文章

ESP32 Bluedroid 篇(1)—— ibeacon 广播

前言 前面我们已经了解了 ESP32 的 BLE 整体架构&#xff0c;现在我们开始实际学习一下Bluedroid 从机篇的广播和扫描。本文将会以 ble_ibeacon demo 为例子进行讲解&#xff0c;需要注意的一点是。ibeacon 分为两个部分&#xff0c;一个是作为广播者&#xff0c;一个是作为观…

Sharp.js:简单而又实用的图像处理库

前言 在现代Web开发中&#xff0c;图像处理是一个不可或缺的部分。 前端开发者经常需要处理图像&#xff0c;以确保它们在不同的设备和分辨率上都能保持良好的显示效果。 sharp.js是一个高性能的Node.js模块&#xff0c;它利用了libvips库&#xff0c;提供了快速且高效的图像…

ERROR [internal] load metadata for docker.io/library/openjdk:8

ERROR: failed to solve: DeadlineExceeded: DeadlineExceeded: DeadlineExceeded: openjdk:8: failed to do request: Head “https://registry-1.docker.io/v2/library/openjdk/manifests/8”: dial tcp 202.160.129.6:443: i/o timeout 在构建docker镜像时从docker.io/libr…

探究Spring的单例设计模式--单例Bean

Spring的单例设计模式 在Spring框架中&#xff0c;单例设计模式是一种常见且重要的设计模式&#xff0c;主要用于确保在应用程序的生命周期中仅创建一个特定的Bean实例 一、什么是单例设计模式&#xff1f; 单例设计模式是一种创建型设计模式&#xff0c;确保一个类只有一个…

Apollo Planning2.0决策规划算法代码详细解析 (3):PlanningComponent框架介绍

Apollo Planning 2.0的框架更新涉及多个方面&#xff0c;这些更新旨在提升自动驾驶系统的灵活性、可扩展性和性能。 以下是Apollo Planning 2.0 的框架图&#xff1a; 其中&#xff0c;Apollo的PlanningComponent在自动驾驶系统中扮演着至关重要的角色。其主要作用可以归纳为以…

Pinia从安装到使用

什么是Pinia 添加Pinia到vue项目 使用Pinia实现计数器案例 counter.js import {defineStore} from "pinia"; import {ref} from "vue";export const useCounterStore defineStore(coutner,()>{//定义数据&#xff08;state&#xff09;const count r…

DualGS:高效人体体积视频渲染技术,实现复杂4D数字人表演的实时播放引言

随着虚拟现实(VR)和增强现实(AR)技术的发展,对高质量、低延迟的人体体积视频的需求日益增长。传统的视频压缩和渲染方法在处理复杂的4D人体动作时往往面临性能瓶颈。为了解决这一问题,研究人员开发了一种名为DualGS的新型高效人体体积视频渲染技术。本文将详细介绍DualGS…

Vue ElemetUI table实现双击修改编辑某个内容

1、使用cell-dblclick事件&#xff0c;当双击时触发事件 <el-table cell-dblclick"handleCellDblClick" 2、单元格设置 主要重点为判断双击时切换input框&#xff0c;然后绑定ref&#xff0c;设置失去焦点时触发点方法&#xff0c;与按enter键触发点方法 <…