天天看點

設計模式(十)享元模式Flyweight(結構型)

說明:

相對于其它模式,flyweight模式在php實作似乎沒有太大的意義,因為php的生命周期就在一個請求,請求執行完了,php占用的資源都被釋放。我們隻是為了學習而簡單做了介紹。

1. 概述

面向對象技術可以很好地解決系統一些靈活性或可擴充性或抽象性的問題,但在很多情況下需要在系統中增加類和對象的個數。當對象數量太多時,将導緻運作代價過高,帶來性能下降等問題。比如: 例子1:圖形應用中的圖元等對象、字處理應用中的字元對象等。
設計模式(十)享元模式Flyweight(結構型)

</blockquote>

2.解決方案:

          享元模式(flyweight):對象結構型模式運用共享技術有效地支援大量細粒度的對象。         它使用共享物件,用來盡可能減少記憶體使用量以及分享資訊給盡可能多的相似物件;它适合用于當大量物件隻是重複因而導緻無法令人接受的使用大量記憶體。通常物件中的部分狀态是可以分享。常見做法是把它們放在外部資料結構,當需要使用時再将它們傳遞給享元。

4. 适用性

1)一個應用程式使用大量相同或者相似的對象,造成很大的存儲開銷。 2)對象的大部分狀态都可以外部化,可以将這些外部狀态傳入對象中。 3)如果删除對象的外部狀态,那麼可以用相對較少的共享對象取代很多組對象。 4) 應用程式不依賴于對象辨別。由于flyweight對象可以被共享,對于概念上明顯有别的對象,辨別測試将傳回真值。 5)使用享元模式需要維護一個存儲享元對象的享元池,而這需要耗費資源,是以,應當在多次重複使用享元對象時才值得使用享元模式

5.結構

設計模式(十)享元模式Flyweight(結構型)

6.構模組化式的組成

1) 抽象享元類(flyweight):描述一個接口,通過這個接口flyweight可以接受并作用于外部狀态。 2) 具體享元類(concreteflyweight):實作flyweight接口 ,并為内部狀态( 如果有的話 )增加存儲空間 。concreteflyweight對象必須是可共享的。它所存儲的狀态必須是内部的;即,它必須獨立于concreteflyweight對象的場景。 3) 非共享具體享元類(unsharedconcreteflyweight):— 并非所有的flyweight子類都需要被共享。flyweight接口使共享成為可能,但它并不強制共享。在flyweight對象結構的某些層次,unsharedconcreteflyweight對象通常将concreteflyweight對象作為子節點。 4) 享元工廠類(flyweightfactory):建立并管理flyweight對象, 確定合理地共享flyweight。本角色必須保證享元對象可以被系統适當地共享。當一個用戶端對象調用一個享元對象   flyweight的時候,享元工廠角色(flyweight factory對象)會檢查系統中是否已經有一個符合要求的享元對象。如果已經有了,享元工廠角色就應當提供這個已有的享元對象;如果系統中沒有一個适當的享元對象的話,享元工廠角色就應當建立一個合适的享元對象。 5)客戶(client):維持一個對flyweight的引用。計算或存儲一個(多個)flyweight的外部狀态。

7. 效果

享元模式的優點: 1)享元模式的優點在于它可以極大減少記憶體中對象的數量,使得相同對象或相似對象在記憶體中隻儲存一份。 2)享元模式的外部狀态相對獨立,而且不會影響其内部狀态,進而使得享元對象可以在不同的環境中被共享。 享元模式的缺點: 1)享元模式使得系統更加複雜,需要分離出内部狀态和外部狀态,這使得程式的邏輯複雜化。 2)為了使對象可以共享,享元模式需要将享元對象的狀态外部化,而讀取外部狀态使得運作時間變長。

8.實作

享元模式可以分成單純享元模式和複合享元模式兩種形式。 【單純享元模式】   在單純的享元模式中,所有的享元對象都是可以共享的。 源代碼: [php] view plain copy &lt;?php   /**   * 單純享元模式    * @author guisu   */    * 抽象享元角色  abstract class flyweight {       /**       * 示意性方法       * @param string $state 外部狀态       */       abstract public function operation($state);   }    * 具體享元角色  class concreteflyweight extends flyweight {       private $_intrinsicstate = null;        * 構造方法       * @param string $state  内部狀态      public function __construct($state) {           $this-&gt;_intrinsicstate = $state;       }       public function operation($state) {           echo 'concreteflyweight operation, intrinsic state = ' . $this-&gt;_intrinsicstate           . ' extrinsic state = ' . $state . '&lt;br /&gt;';    * 享元工廠角色  class flyweightfactory {       private $_flyweights;       public function __construct() {           $this-&gt;_flyweights = array();       public function getflyweigth($state) {           if (isset($this-&gt;_flyweights[$state])) {               return $this-&gt;_flyweights[$state];           } else {               return $this-&gt;_flyweights[$state] = new concreteflyweight($state);           }   class client{       static function main (){           $flyweightfactory = new flyweightfactory();           $flyweight = $flyweightfactory-&gt;getflyweigth('state a');           $flyweight-&gt;operation('other state a');           $flyweight = $flyweightfactory-&gt;getflyweigth('state b');           $flyweight-&gt;operation('other state b');   ?&gt;   【複合享元模式】 複合享元模式對象是由一些單純享元使用合成模式加以複合而成 複合享元角色所代表的對象是不可以共享的,但是一個複合享元對象可以分解成為多個本身是單純享元對象的組合。  * 複合享元模式   *    * 不共享的具體享元,用戶端直接調用  class unsharedconcreteflyweight extends flyweight {           foreach ($this-&gt;_flyweights as $flyweight) {               $flyweight-&gt;operation($state);       public function add($state, flyweight $flyweight) {           $this-&gt;_flyweights[$state] = $flyweight;   * 享元工廠角色  */           if (is_array($state)) { //  複合模式               $uflyweight = new unsharedconcreteflyweight();               foreach ($state as $row) {                   $uflyweight-&gt;add($row, $this-&gt;getflyweigth($row));               }               return $uflyweight;           } else if (is_string($state)) {               if (isset($this-&gt;_flyweights[$state])) {                   return $this-&gt;_flyweights[$state];               } else {                   return $this-&gt;_flyweights[$state] = new concreteflyweight($state);               return null;           /* 複合對象*/           $uflyweight = $flyweightfactory-&gt;getflyweigth(array('state a', 'state b'));           $uflyweight-&gt;operation('other state a');  

9.

與其他相關模式

用戶端要引用享元對象,是通過工廠對象建立或者獲得的,用戶端每次引用一個享元對象,都是可以通過同一個工廠對象來引用所需要的享元對象。是以,可以将享元工廠設計成單例模式,這樣就可以保證用戶端隻引用一個工廠執行個體。因為所有的享元對象都是由一個工廠對象統一管理的,是以在用戶端沒有必要引用多個工廠對象。不管是單純享元模式還是複合享元模式中的享元工廠角色,都可以設計成為單例模式,對于結果是不會有任何影響的。      composite模式:flyweight模式通常和composite 模式結合起來,用共享葉結點的有向無環圖實作一個邏輯上的層次結構。複合享元模式實際上是單純享元模式與合成模式的組合。單純享元對象可以作為樹葉對象來講,是可以共享的,而複合享元對象可以作為樹枝對象, 是以在複合享元角色中可以添加聚集管理方法。通常,最好用flyweight實作state 和strategy 對象。

10.總結

1)  享元模式是一個考慮系統性能的設計模式,通過使用享元模式可以節約記憶體空間,提高系統的性能。  2)  享元模式的核心在于享元工廠類,享元工廠類的作用在于提供一個用于存儲享元對象的享元池,使用者需要對象時,首先從享元池中擷取,如果享 元池中不存在,則創       建一個新的享元對象傳回給使用者,并在享元池中儲存該新增對象。 3)   享元模式以共享的方式高效地支援大量的細粒度對象,享元對象能做到共享的關鍵是區分内部狀态(internal state)和外部狀态(external state)。        (1)   内部狀态是存儲在享元對象内部并且不會随環境改變而改變的狀态,是以内部狀态可以共享。        (2)   外部狀态是随環境改變而改變的、不可以共享的狀态。享元對象的外部狀态必須由用戶端儲存,并在享元對象被建立之後,在需要使用的時候 再傳入到享元對               象内部。一個外部狀态與另一個外部狀态之間是互相獨立的。