1定義 使用共用對象可有效的支持大量細粒度的對象 2類圖 角色分析 Flyweight抽象享元角色,一個產品的抽象,定義內部狀態和外部狀態的介面或者實現 ConcreteFlyweight具體享元角色,實現抽象角色定義的業務。註:內部狀態處理和環境無關 unsharedConcreteFlyweig ...
1定義
使用共用對象可有效的支持大量細粒度的對象
2類圖
角色分析
Flyweight抽象享元角色,一個產品的抽象,定義內部狀態和外部狀態的介面或者實現
ConcreteFlyweight具體享元角色,實現抽象角色定義的業務。註:內部狀態處理和環境無關
unsharedConcreteFlyweight不可共用的享元角色,不存在外部狀態或者安全要求,不能夠使用共性技術的對象,該對象一般不會出現在享元工廠中
Flyweight享元工廠,就是構造一個池容器,同時提供從翅中獲得對象的方法
3實現
#pragma once #include<hash_map> #include<iostream> using namespace std; class Flyweight { private: //內部狀態 string intrinsic; protected: //外部狀態 const string extrainsic; public: Flyweight(string _ex) :extrainsic ( _ex) { } //定義業務操作 virtual void operate(){} string getIntrinsic() { return intrinsic; } void setIntrinsic(string _in) { intrinsic = _in; } }; class ConcreteFlyweight1 :public Flyweight { public: ConcreteFlyweight1(string ex) :Flyweight(ex) {} void operate() { //根據外部邏輯進行業務處理 cout << "1根據外部邏輯進行業務處理!" << endl; } }; class ConcreteFlyweight2 :public Flyweight { public: ConcreteFlyweight2(string ex) :Flyweight(ex) {} void operate() { //根據外部邏輯進行業務處理 cout << "2根據外部邏輯進行業務處理!" << endl; } }; class FlyweightFactory { private: static hash_map<string, Flyweight*> pool; public: Flyweight* getFlyweight(string ex) { hash_map<string, Flyweight*>::iterator it = pool.find(ex); if (it == pool.end()) { cout << "Creat Flyweight1" << endl; pool[ex] = new ConcreteFlyweight1(ex); } return pool[ex]; } }; hash_map<string, Flyweight*> FlyweightFactory::pool = hash_map<string,Flyweight*>(); class Client { public: void operator()() { FlyweightFactory ff; Flyweight * pf = ff.getFlyweight("lianglihui"); pf->operate(); } };
4應用
①優點
是一個簡單的模式,可以大大減少程式創建的對象,降低記憶體占用,增強性能
②缺點
提高系統複雜性,需要分離狀態,且外部狀態不應該隨著內部狀態的改變而改變
③使用場景
系統中存在大量的相似對象
細粒度的對象都具有較接近的外部狀態,而內部狀態和環境無關。
需要緩衝池的場景
5擴展
① 線程安全問題,因為共用對象比較少,多個線程同時去訪問通過外部狀態對其內部狀態訪問就出現了線程安全問題。--》使用享元模式時,保證享元對象足夠多,同時處理掉線程安全問題就好
②性能問題
優化:將外部狀態封裝成類,通過橋梁模式進行嫁接,減少耦合,提高效率/使用系統內置類型作為外部狀態
(ps因為池中檢測會有調用消耗)
6對象池vs享元模式
享元模式可以實現對象池
對象池著重在對象的復用,池中的每個對象都是可替換的,從同一個池中獲得A對象和B對象對客戶端來講是完全相同的,主要解決復用。
享元模式側重共用問題,如何建立多個可共用的細粒度對象則是其關註的重點。