首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

設計模式實作系列(十三):Flyweight 享元模式 - 共享細粒度物件大幅降低記憶體佔用

     編輯:關於C++

模式意圖

運用共享技術有效地支援大量細粒度的物件。

UML 結構圖

Flyweight Pattern UML

核心解析:內部狀態與外部狀態

  • 內部狀態: 可共享、不隨環境變化(如字元字型、圖示資料),儲存於享元物件內部。
  • 外部狀態: 隨環境變化、不可共享(如字元位置、顏色),由客戶端傳入操作時提供。
  • 享元工廠: 管理享元池(std::list/unordered_map),GetFlyweight(key) 先查找池中是否存在,否則建立新物件並加入池中。
  • 非共享享元: 部分物件不適合共享(如特定上下文的組合),直接由客戶端實例化,不經工廠。

C++ 完整實作(僅示範可共享部分)

1. Flyweight.h

#ifndef FLYWEIGHT_H
#define FLYWEIGHT_H

#include <string>
#include <list>
typedef std::string STATE;

class Flyweight {
public:
    virtual ~Flyweight() {}
    STATE GetIntrinsicState() const;
    virtual void Operation(STATE& ExtrinsicState) = 0;
protected:
    Flyweight(const STATE& state) : m_State(state) {}
private:
    STATE m_State;
};

class FlyweightFactory {
public:
    FlyweightFactory() {}
    ~FlyweightFactory();
    Flyweight* GetFlyweight(const STATE& key);
private:
    std::list<Flyweight*> m_listFlyweight;
};

class ConcreteFlyweight : public Flyweight {
public:
    ConcreteFlyweight(const STATE& state) : Flyweight(state) {}
    virtual ~ConcreteFlyweight() {}
    virtual void Operation(STATE& ExtrinsicState);
};

#endif

2. Flyweight.cpp

#include "Flyweight.h"
#include <iostream>

STATE Flyweight::GetIntrinsicState() const { return m_State; }

FlyweightFactory::~FlyweightFactory() {
    for (auto p : m_listFlyweight) delete p;
    m_listFlyweight.clear();
}

Flyweight* FlyweightFactory::GetFlyweight(const STATE& key) {
    for (auto p : m_listFlyweight) {
        if (p->GetIntrinsicState() == key) {
            std::cout << "The Flyweight: " << key << " already exists\n";
            return p;
        }
    }
    std::cout << "Creating a new Flyweight: " << key << std::endl;
    Flyweight* fw = new ConcreteFlyweight(key);
    m_listFlyweight.push_back(fw);
    return fw;
}

void ConcreteFlyweight::Operation(STATE& ExtrinsicState) {
    // 使用外部狀態執行操作
}

3. Main.cpp

#include "Flyweight.h"

int main() {
    FlyweightFactory factory;
    factory.GetFlyweight("hello"); // 建立新
    factory.GetFlyweight("world"); // 建立新
    factory.GetFlyweight("hello"); // 復用現有
    return 0;
}

效能與現代 C++ 優化

  • 使用 std::unordered_map<Key, std::shared_ptr<Flyweight>> 替代 list,查找複雜度從 O(n) 降為 O(1)。
  • 鍵值可設計為複合型別(如 struct FontKey { string family; int size; bool bold; }),需提供雜湊函數。
  • 執行緒安全:GetFlyweight 需加鎖或使用無鎖資料結構。

適用場景

  • 文字編輯器字元物件(每字元一物件會爆記憶體)。
  • 圖形編輯器大量相同圖示/圖元。
  • 遊戲粒子系統、地圖瓦片、資料庫連線池、執行緒池。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved