【第十节】C++设计模式(结构型模式)-Flyweight( 享元)模式

ops/2025/2/28 14:59:53/

目录

一、问题背景

二、模式选择

三、代码实现

四、总结讨论


一、问题背景

        享元模式(Flyweight Pattern)在对象存储优化中的应用

        在面向对象系统的设计与实现中,创建对象是最常见的操作之一。然而,如果一个应用程序使用了过多的对象,尤其是大量轻量级(细粒度)的对象,可能会导致巨大的存储开销。例如,在文档编辑器的设计中,如果为每个字母创建一个独立的对象,系统中可能会出现大量重复的对象,从而造成存储浪费。例如,字母“a”在文档中可能出现 100,000 次,实际上这 100,000 个“a”可以共享同一个对象。

        然而,由于不同位置的字母“a”可能有不同的显示效果(如字体、大小等),我们可以将对象的状态分为“内部状态”和“外部状态”。内部状态是对象共享的、不变的部分,而外部状态则可以在需要时作为参数传递给对象(例如在显示时传递字体、大小等信息)。

二、模式选择

        上述问题可以通过**享元模式(Flyweight Pattern)**来解决。享元模式的核心思想是通过共享大量细粒度对象来减少存储开销。其典型结构如下:

        FlyweightFactory:类似于工厂模式的对象构造工厂,用于管理对象的创建和共享。
        Flyweight:享元对象的基类,定义了内部状态和外部状态的处理方式。
        ConcreteFlyweight:具体的享元对象实现,包含内部状态。

三、代码实现

        以下是享元模式的完整实现代码,采用 C++ 编写。

代码片段 1:Flyweight.h

#ifndef _FLYWEIGHT_H_
#define _FLYWEIGHT_H_#include <string>
using namespace std;class Flyweight {
public:virtual ~Flyweight();virtual void Operation(const string& extrinsicState); // 外部状态的处理string GetIntrinsicState(); // 获取内部状态
protected:Flyweight(string intrinsicState); // 构造函数,初始化内部状态
private:string _intrinsicState; // 内部状态
};class ConcreteFlyweight : public Flyweight {
public:ConcreteFlyweight(string intrinsicState); // 构造函数~ConcreteFlyweight();void Operation(const string& extrinsicState); // 外部状态的处理
};#endif //~_FLYWEIGHT_H_

代码片段 2:Flyweight.cpp

#include "Flyweight.h"
#include <iostream>
using namespace std;Flyweight::Flyweight(string intrinsicState) {this->_intrinsicState = intrinsicState;
}Flyweight::~Flyweight() {}void Flyweight::Operation(const string& extrinsicState) {// 默认实现为空
}string Flyweight::GetIntrinsicState() {return this->_intrinsicState;
}ConcreteFlyweight::ConcreteFlyweight(string intrinsicState) : Flyweight(intrinsicState) {cout << "ConcreteFlyweight Build....." << intrinsicState << endl;
}ConcreteFlyweight::~ConcreteFlyweight() {}void ConcreteFlyweight::Operation(const string& extrinsicState) {cout << "ConcreteFlyweight: 内蕴 [" << this->GetIntrinsicState() << "] 外蕴 [" << extrinsicState << "]" << endl;
}

代码片段 3:FlyweightFactory.h

#ifndef _FLYWEIGHTFACTORY_H_
#define _FLYWEIGHTFACTORY_H_#include "Flyweight.h"
#include <string>
#include <vector>
using namespace std;class FlyweightFactory {
public:FlyweightFactory();~FlyweightFactory();Flyweight* GetFlyweight(const string& key); // 获取享元对象
protected:
private:vector<Flyweight*> _fly; // 对象池
};#endif //~_FLYWEIGHTFACTORY_H_

代码片段 4:FlyweightFactory.cpp

#include "FlyweightFactory.h"
#include <iostream>
#include <cassert>
using namespace std;FlyweightFactory::FlyweightFactory() {}FlyweightFactory::~FlyweightFactory() {}Flyweight* FlyweightFactory::GetFlyweight(const string& key) {vector<Flyweight*>::iterator it = _fly.begin();for (; it != _fly.end(); it++) {// 如果对象已存在,则直接返回if ((*it)->GetIntrinsicState() == key) {cout << "already created by users...." << endl;return *it;}}// 否则创建新对象并加入对象池Flyweight* fn = new ConcreteFlyweight(key);_fly.push_back(fn);return fn;
}

代码片段 5:main.cpp

#include "Flyweight.h"
#include "FlyweightFactory.h"
#include <iostream>
using namespace std;int main(int argc, char* argv[]) {FlyweightFactory* fc = new FlyweightFactory();Flyweight* fw1 = fc->GetFlyweight("hello"); // 获取享元对象Flyweight* fw2 = fc->GetFlyweight("world!"); // 获取享元对象Flyweight* fw3 = fc->GetFlyweight("hello"); // 获取享元对象return 0;
}

代码说明

        享元模式在实现过程中,主要是为共享对象提供一个存放的“仓库”(对象池)。这里通过 C++ STL 中的 `vector` 容器来实现对象池的管理。需要注意的是,对象池的管理策略(查找、插入等)对性能有很大影响。这里使用了简单的顺序遍历来查找对象,但实际应用中可以使用更高效的索引策略,例如哈希表。

四、总结讨论

        享元模式通过共享细粒度对象,有效地减少了系统中的对象数量,从而降低了存储开销。它特别适用于需要创建大量相似对象的场景,如文档编辑器、游戏中的粒子系统等。通过合理使用享元模式,可以显著提高系统的性能和资源利用率。

        在以后讲到的状态模式(State Pattern)和策略模式(Strategy Pattern)中,可能会产生大量的对象,因此可以通过享元模式来优化存储开销。享元模式的核心思想是共享对象,从而减少系统中对象的数量,降低存储和计算资源的消耗。

参考学习:设计模式精解-GoF 23 设计模式解析


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

相关文章

React 第二十七节 <StrictMode> 的使用方法及注意事项

一、StrictMode 的核心作用 React StrictMode 是 React 16.3 引入的开发辅助工具&#xff0c;通过主动触发特殊检查帮助开发者提前发现潜在问题。它像一位严格的代码审查员&#xff0c;在开发阶段执行以下关键任务&#xff1a; 1、副作用探测器 2、故意双调用构造函数、rende…

5分钟学习-什么事前端HTML文件

以下从 HTML 文件的基本概念、结构、常用标签等方面&#xff0c;以新手容易理解的方式进行介绍&#xff0c;并给出示例帮助新手看懂 HTML 文件。 1. 什么是 HTML 文件 HTML 即超文本标记语言&#xff08;HyperText Markup Language&#xff09;&#xff0c;它是用于创建网页的…

Java I/O 与 NIO 核心区别及应用场景详解

一、核心概念对比 特性传统 I/O (BIO)NIO (New I/O)模型同步阻塞模型同步非阻塞模型数据流方向单向流&#xff08;InputStream/OutputStream&#xff09;双向通道&#xff08;Channel&#xff09;数据操作单元基于字节/字符流基于缓冲区&#xff08;Buffer&#xff09;线程模型…

MySQL Workbench安装教程以及菜单汉化

WorkBench的下载 直接给下载MySql WorkBench的链接&#xff0c;直接进入正题&#xff1a;MySQL :: Download MySQL Workbench[这里是图片001]https://dev.mysql.com/downloads/workbench/进入了下载界面&#xff1a; &#xff08;安装路径自己看着办&#xff0c;注意安装路径不…

哈希封装unordered_map/unordered_set

前言 看这篇博客之前请先看&#xff1a; C | 哈希表-CSDN博客 &#x1f493; 个人主页&#xff1a;普通young man-CSDN博客 ⏩ 文章专栏&#xff1a;C_普通young man的博客-CSDN博客 ⏩ 本人giee: 普通小青年 (pu-tong-young-man) - Gitee.com 若有问题 评论区见&#x1f4dd…

嵌入式八股,Linux驱动三大基础类

在Linux内核开发中&#xff0c;驱动程序的设计和实现通常基于三大基础类&#xff08;或框架&#xff09;&#xff0c;分别是&#xff1a; 字符设备驱动&#xff08;Character Device Drivers&#xff09; 块设备驱动&#xff08;Block Device Drivers&#xff09; 网络设备驱…

【HeadFirst系列之HeadFirst设计模式】第10天之迭代器与组合模式:遍历与管理的艺术

迭代器与组合模式&#xff1a;遍历与管理的艺术 在《Head First 设计模式》中&#xff0c;**迭代器模式&#xff08;Iterator Pattern&#xff09;和组合模式&#xff08;Composite Pattern&#xff09;**是两个非常重要的设计模式。迭代器模式帮助我们遍历集合中的元素&#…

51单片机-按键

1、独立按键 1.1、按键介绍 轻触开关是一种电子开关&#xff0c;使用时&#xff0c;轻轻按开关按钮就可使开关接通&#xff0c;当松开手时&#xff0c;开关断开。 1.2、独立按键原理 按键在闭合和断开时&#xff0c;触点会存在抖动现象。P2\P3\P1都是准双向IO口&#xff0c;…