甜品網站模板/圖片外鏈在線生成網址
1、定義與動機
-
概述:享元模式和單例模式一樣,都是為了解決程序的性能問題。面向對象很好地解決了"抽象"的問題,但是必不可免得要付出一定的代價。對于通常情況來講,面向對象的成本大豆可以忽略不計。但是某些情況,面向對象所帶來的成本必須謹慎處理。
-
定義:運用共享技術有效地支持大量細粒度的對象。
-
動機:
- 在軟件系統(tǒng)中采用純粹對象方案的問題在于大量細粒度的對象會很快充斥在系統(tǒng)中,而帶來很高的運行時代價——主要指內存需求方面的代價。
- 如何避免大量細粒度對象問題的同時,讓外部客戶程序仍然能夠透明地使用面向對象的方式來進行操作?
-
個人理解:例如在電腦中存在大量的字體
-
首先:電腦在啟動時不可能把所有的字體的文件渲染方式或者字體樣式都加載到內存中,而應該是在需要的時候去加載
-
其次:當電腦字體需要更改時會創(chuàng)建一個字體對象,而wps/office中的字體也會有一個對象字體。
-
當word和ppt中的字體相同時,應該是只需要創(chuàng)建一個對象,因為字體這個東西應該說只讀(只用來渲染,總不可能更改樣式吧),因此這兩個對象應該使用同一個對象即可,不應該在需要的地方就new!
-
很明顯這里也是解決一個性能問題的設計模式
-
比較常見的一個實用地方:各種池子,線程池、內存池、連接池…,它們都應該創(chuàng)建好需要的時候去取一個就行,用完了還回去;而不是需要的時候new一個。
-
2、享元模式
- 對于Font類創(chuàng)建出來的對象應該只能讀,不允許修改
- FontFactory字體工廠負責取字體,如果沒有就new一個字體然后存放在一個數據結構中(這里用無序map)
#include <iostream>
#include <unordered_map>
#include <string>
class Font{
private:// unique object keystd::string key;// object state ...
public:Font(const std::string &_key){// ...}
};class FontFactory{
private:std::unordered_map<std::string, Font*> fontPool;
public:Font *GetFont(const std::string &key){if(fontPool.find(key) == fontPool.end()){Font *font = new Font(key);fontPool.insert(std::make_pair(key, font));}return fontPool[key];}
};void process()
{FontFactory* fontFactory = new FontFactory();Font* songStyle = fontFactory->GetFont("宋體");Font* kaiStyle = fontFactory->GetFont("楷體");// ...
}
其實這里沒有設計好:
- FontFactory可以到處創(chuàng)建,可以考慮把FontFactory字體工廠做成一個單例的工廠。
- 字體獲取的多線程安全問題,準確來說獲取應該是沒有線程安全問題的,創(chuàng)建有…
3、總結
- 面向對象很好的解決了抽象性問題,但是作為一個運行在機器中的程序實體,我們需要考慮對象的代價問題。Flyweight主要解決面向對象的代價問題,一般不初級面向隊形的抽象性問題
- Flyweight采用對象共享的做法來降低系統(tǒng)中對象的個數,從而降低細粒度對象給系統(tǒng)帶來的內存壓力。在具體實現方面,要注意對象的狀態(tài)處理(即只讀不修改,否則后續(xù)可能無法重復使用)
- 對象的數量太大從而導致對象內存開銷加大——什么樣的數量才算大?這需要仔細的根據具體應用情況進行評估,而不能憑空臆斷。