轉
問題 在物件導向系統的設計何實現中,建立物件是最為常見的操作。這裡面就有乙個問題:
如果乙個應用程式使用了太多的物件,就會造成很大的儲存開銷。特別是對於大量輕量級(細
粒度)的物件,比如在文件編輯器的設計過程中,我們如果為沒有字母建立乙個物件的話,
系統可能會因為大量的物件而造成儲存開銷的浪費。例如乙個字母「a」在文件**現了
100000 次,而實際上我們可以讓這一萬個字母「a」共享乙個物件,當然因為在不同的位置
可能字母「a」有不同的顯示效果(例如字型和大小等設定不同),在這種情況我們可以為將
物件的狀態分為「外部狀態」和「內部狀態」,將可以被共享(不會變化)的狀態作為內部
狀態儲存在物件中,而外部物件(例如上面提到的字型、大小等)我們可以在適當的時候將
外部物件最為引數傳遞給物件(例如在顯示的時候,將字型、大小等資訊傳遞給物件)。
可以從圖 2-1 中看出,flyweight 模式中有乙個類似 factory 模式的物件構造工廠
flyweightfactory,當客戶程式設計師(client)需要乙個物件時候就會向 flyweightfactory 發出
請求物件的訊息 getflyweight()訊息,flyweightfactory 擁有乙個管理、儲存物件的「倉
庫」(或者叫物件池,vector 實現),getflyweight()訊息會遍歷物件池中的物件,如果已
經存在則直接返回給 client,否則建立乙個新的物件返回給 client。當然可能也有不想被共
享的物件(例如結構圖中的 unshareconcreteflyweight),但不在本模式的講解範圍,故在實
現中不給出。
舉個圍棋的例子,圍棋的棋盤共有361格,即可放361個棋子。現在要實現乙個圍棋程式,該怎麼辦呢?首先要考慮的是棋子棋盤的實現,可以定義乙個棋子的類,成員變數包括棋子的顏色、形狀、位置等資訊,另外再定義乙個棋盤的類,成員變數中有個容器,用於存放棋子的物件。下面給出**表示:
棋子的定義,當然棋子的屬性除了顏色和位置,還有其他的,這裡略去。這兩個屬性足以說明問題。
//棋盤的定義:棋子顏色
enum
piececolor ;
//棋子位置
struct
piecepos
};//
棋子定義
class
piece
~piece() {}
virtual
void
draw() {}
};class blackpiece: public
piece
~blackpiece() {}
void draw()
};class whitepiece: public
piece
~whitepiece() {}
void draw()
};
class客戶的使用方式如下:pieceboard
~pieceboard()
void setpiece(piececolor color, piecepos pos) //
一步棋,在棋盤上放一顆棋子
else
m_vecpiece.push_back(piece);
//加入容器中
}
void clear() //
釋放記憶體
};
int可以發現,棋盤的容器中存放了已下的棋子,而每個棋子包含棋子的所有屬性。一盤棋往往需要含上百顆棋子,採用上面這種實現,占用的空間太大了。如何改進呢?用享元模式。其定義為:運用共享技術有效地支援大量細粒度的物件。main()
在圍棋中,棋子就是大量細粒度的物件。其屬性有內在的,比如顏色、形狀等,也有外在的,比如在棋盤上的位置。內在的屬性是可以共享的,區分在於外在屬性。因此,可以這樣設計,只需定義兩個棋子的物件,一顆黑棋和一顆白棋,這兩個物件含棋子的內在屬性;棋子的外在屬性,即在棋盤上的位置可以提取出來,存放在單獨的容器中。相比之前的方案,現在容器中僅僅存放了位置屬性,而原來則是棋子物件。顯然,現在的方案大大減少了對於空間的需求。
關注pieceboard 的容器,之前是vectorm_vecpiece,現在是vectorm_vecpos。這裡是關鍵。
改進後的
棋子的新定義,只包含內在屬性:
//相應棋盤的定義為:棋子顏色
enum
piececolor ;
//棋子位置
struct
piecepos
};//
棋子定義
class
piece
~piece() {}
virtual
void
draw() {}
};class blackpiece: public
piece
~blackpiece() {}
void draw()
};class whitepiece: public
piece
~whitepiece() {}
void draw()
};
class客戶的使用方式一樣,這裡不重複給出,現在給出享元模式的uml圖,以圍棋為例。棋盤中含兩個共享的物件,黑棋子和白棋子,所有棋子的外在屬性都存放在單獨的容器中。pieceboard
~pieceboard()
void
setpiece(piececolor color, piecepos pos)
else
m_vecpos.push_back(pos);}};
uml類圖:
設計模式 11 享元模式
舉個圍棋的例子,圍棋的棋盤共有361格,即可放361個棋子。現在要實現乙個圍棋程式,該怎麼辦呢?首先要考慮的是棋子棋盤的實現,可以定義乙個棋子的類,成員變數包括棋子的顏色 形狀 位置等資訊,另外再定義乙個棋盤的類,成員變數中有個容器,用於存放棋子的物件。下面給出 表示 棋子的定義,當然棋子的屬性除了...
11 享元模式
一 享元模式 享元設計模式通過為相似物件引入資料共享來最小化記憶體使用,提公升效能。享元模式定義如下 使用共享物件支援大量細粒度物件。大量細粒度的物件的支援共享,可能會涉及這些物件的兩類資訊 內部狀態資訊和外部狀態資訊。內部狀態資訊就是可共享出來的資訊,它們儲存在享元物件內部,不會隨著特定環境的改變...
(11)享元模式
享元模式用於減少建立物件的數量,以減少記憶體占用和提高效能。享元模式嘗試重用現有的同類物件,如果未找到匹配的物件,則建立新物件。享元模式用得比較多的是池化技術,如常量池,執行緒池,連線池等等。import j a.util.hashmap import j a.util.map 享元模式 publi...