【第十節】C++設計模式(結構型模式)-Flyweight( 享元)模式

目錄

一、問題背景

二、模式選擇

三、代碼實現

四、總結討論


一、問題背景

????????享元模式(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.pswp.cn/news/896471.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/896471.shtml
英文地址,請注明出處:http://en.pswp.cn/news/896471.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

spring boot 2.7 + seata +微服務 降級失敗問題修復

文章引流 一個簡單而使用的API管理工具 版本號 spring boot 2.7.17 spring-cloud-dependencies 2021.0.8 spring-cloud-circuitbreaker-resilience4j 2.1.7 spring-cloud-starter-alibaba-seata 2021.1 jdk 1.8原因分析 未配置屬性 feign.circuitbreaker.enabledtrue # 未…

實現實時數據倉庫開源項目

根據你的需求&#xff0c;以下是一些可以實現類似 ClickHouse 的實時數倉功能的項目&#xff0c;這些項目提供了高性能的數據處理和分析能力&#xff0c;適合實時數據倉庫的場景&#xff1a; 1. Apache Doris Apache Doris 是一個開源的實時數據倉庫&#xff0c;支持高吞吐量…

【字符串】最長公共前綴 最長回文子串

文章目錄 14. 最長公共前綴解題思路&#xff1a;模擬5. 最長回文子串解題思路一&#xff1a;動態規劃解題思路二&#xff1a;中心擴散法 14. 最長公共前綴 14. 最長公共前綴 ? 編寫一個函數來查找字符串數組中的最長公共前綴。 ? 如果不存在公共前綴&#xff0c;返回空字符…

Maven的傳遞性、排除依賴、生命周期、插件

一、Maven的傳遞性 藍色背景中的兩個jar包是projectA的直接依賴&#xff0c;其余的Jar包是projectA的間接依賴。 projectA可以使用直接依賴&#xff0c;也可以使用間接依賴。 maven-projectB項目引入了maven-projectC(整個項目打成了jar包&#xff09;和junit兩個jar包。 ma…

API,URL,Token,XML,JSON是干嘛的

API&#xff0c;URL&#xff0c;Token&#xff0c;XML&#xff0c;JSON是干嘛的 API的作用 API&#xff08;Application Programming Interface&#xff0c;應用程序編程接口&#xff09;是一組定義和協議&#xff0c;用于構建和交互軟件應用程序。API允許不同的軟件系統之間…

Spring Boot操作MaxComputer(保姆級教程)

目錄 引言 一、引入依賴 二、配置文件 application.properties&#xff08;信息用自己的奧&#xff09; 三、實體類User.java 四、UserController 五、UserService 六、UserDao 七、UserDao.xml 八、postman 訪問&#xff0c;成功查詢數據 附件(修改和刪除數據) 引言…

Java【網絡原理】(2)初識網絡續與網絡編程

目錄 1.前言 2.正文 2.1TCP協議與UDP協議 2.2socket API進行網絡編程 2.2.1DatagramPacket類 2.2.1.1發送數據報 2.2.1.2接收數據報 2.2.1.3獲取數據報內容 2.2.1.4設置數據報內容 2.2.2DatagramSocket類 2.2.2.1構造方法 2.2.2.2常用方法 2.2.3具體代碼與解釋 3…

【Oracle專欄】sqlplus顯示設置+腳本常用顯示命令

Oracle相關文檔&#xff0c;希望互相學習&#xff0c;共同進步 風123456789&#xff5e;-CSDN博客 1.內容概述 本文主要針對oracle 運維中常用知識點進行整理&#xff0c;包括&#xff1a; 1&#xff09;sqlplus模式下&#xff0c;為了方便查詢設置相應的行寬、列寬、行數。…

在一臺win10專業版設備上使用docker的怪現象

這臺設備上&#xff0c;wsl環境無法直接安裝docker&#xff0c;必須要在宿主機安裝Docker Desktop.然后&#xff0c;在wsl運行前&#xff0c;要先啟動docker desktop&#xff0c;否則&#xff0c;你看不到你自己創建的映像。 然后如果沒有docker desktop加持&#xff0c;你在嘗…

Unity 中Sirenix.OdinInspector 插件常用功能梳理

案例一 public class PracticeAssets : ScriptableObject {[SerializeField][Searchable][ListDrawerSettings(ShowIndexLabels true)][LabelText("練習版數據列表")]public List<PracticeData> Practicies new List<PracticeData>(); } 1. Serialize…

C++ | 面向對象 | 類

&#x1f47b;類 &#x1f47e;語法格式 class className{Access specifiers: // 訪問權限DataType variable; // 變量returnType functions() { } // 方法 };&#x1f47e;訪問權限 class className {public:// 公有成員protected:// 受保護成員private:// 私有成員 }…

從零開始用react + tailwindcss + express + mongodb實現一個聊天程序(五) 實現登錄功能

1.登錄頁面 完善登錄頁面 和注冊差不多 直接copy signUpPage 內容 再稍微修改下 import { useState } from "react"; import { useAuthStore } from "../store/useAuthStore"; import { MessageSquare,Mail,Lock,Eye, EyeOff,Loader2} from "lucide…

Spring Boot電影評論網站系統設計與實現

隨著互聯網和娛樂產業的發展&#xff0c;電影評論網站逐漸成為人們分享觀影體驗、交流影評的重要平臺。本文將介紹一個基于Spring Boot框架開發的電影評論網站系統的功能設計與實現方案。 功能模塊概述 該電影評論網站系統分為管理員模塊和用戶模塊兩大核心部分&#xff0c;以…

XFeat:輕量級的深度學習圖像特征匹配

一、引言&#xff1a;圖像特征匹配的挑戰與XFeat的突破 在計算機視覺領域&#xff0c;圖像特征匹配是視覺定位&#xff08;Visual Localization&#xff09;、三維重建&#xff08;3D Reconstruction&#xff09;、增強現實&#xff08;AR&#xff09;等任務的核心基礎。傳統方…

【TVM教程】為 NVIDIA GPU 自動調度神經網絡

Apache TVM 是一個深度的深度學習編譯框架&#xff0c;適用于 CPU、GPU 和各種機器學習加速芯片。更多 TVM 中文文檔可訪問 →https://tvm.hyper.ai/ 作者&#xff1a;Lianmin Zheng 針對特定設備和工作負載的自動調優對于獲得最佳性能至關重要。本文介紹如何使用 auto-sched…

postgresql postgis擴展相關

項目 下載地址 http://rpmfind.net/linux/rpm2html/search.php?queryprotobuf(x86-64) Postgis Index of /postgis/source/ proj4 Index of /proj/ geos Index of /geos/ libxml2 ftp://xmlsoft.org/libxml2/ Index of /sources Json-c Releases json-c/json-c G…

解鎖健康密碼,擁抱養生生活

在快節奏的現代生活中&#xff0c;健康養生愈發重要&#xff0c;它是我們保持活力、預防疾病、享受美好生活的關鍵。那究竟如何開啟健康養生之旅呢&#xff1f; 合理飲食是養生基石。遵循 “食物多樣&#xff0c;谷類為主” 原則&#xff0c;每日攝入谷薯類、蔬菜水果、畜禽魚蛋…

JavaWeb中的cookie使用

Cookie 1、Cookie是服務端向客戶端響應的一小段數據&#xff0c;最終存放在客戶端中&#xff1b;之后客戶端每次向服務端發送請求&#xff0c;都會在請求頭中攜帶cookie 2、cookie是有時效性的&#xff0c;默認是Session級別&#xff08;整個瀏覽器關閉才會消失&#xff0c;內存…

el-input實現金額輸入

需求&#xff1a;想要實現一個輸入金額的el-input&#xff0c;限制只能輸入數字和一個小數點。失焦數字轉千分位&#xff0c;聚焦轉為數字&#xff0c;超過最大值&#xff0c;紅字提示 效果圖 失焦 聚焦 報錯效果 // 組件limitDialog <template><el-dialog:visible.s…

AcWing 藍橋杯集訓·每日一題2025·密接牛追蹤2

密接牛追蹤2 農夫約翰有 N 頭奶牛排成一排&#xff0c;從左到右依次編號為 1~N。 不幸的是&#xff0c;有一種傳染病正在蔓延。 最開始時&#xff0c;只有一部分奶牛受到感染。 每經過一個晚上&#xff0c;受感染的牛就會將病毒傳染給它左右兩側的牛&#xff08;如果有的話…