最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++設計模式編程之Flyweight享元模式結(jié)構(gòu)詳解

 更新時間:2016年03月16日 10:52:34   作者:夢在天涯  
這篇文章主要介紹了C++設計模式編程的Flyweight享元模式結(jié)構(gòu),享元模式在實現(xiàn)過程中主要是要為共享對象提供一個存放的"倉庫"(對象池),需要的朋友可以參考下

由遇到的問題引出享元模式:

在面向?qū)ο笙到y(tǒng)的設計何實現(xiàn)中,創(chuàng)建對象是最為常見的操作。這里面就有一個問題:如果一個應用程序使用了太多的對象,就會造成很大的存儲開銷。特別是對于大量輕量級(細粒度)的對象,比如在文檔編輯器的設計過程中,我們?nèi)绻麨闆]有字母創(chuàng)建一個對象的話,系統(tǒng)可能會因為大量的對象而造成存儲開銷的浪費。例如一個字母"a"在文檔中出現(xiàn)了100000 次,而實際上我們可以讓這一萬個字母"a"共享一個對象,當然因為在不同的位置可能字母"a"有不同的顯示效果(例如字體和大小等設置不同),在這種情況我們可以為將對象的狀態(tài)分為"外部狀態(tài)"和"內(nèi)部狀態(tài)",將可以被共享(不會變化)的狀態(tài)作為內(nèi)部狀態(tài)存儲在對象中,而外部對象(例如上面提到的字體、大小等)我們可以在適當?shù)臅r候?qū)⑼獠繉ο笞顬閰?shù)傳遞給對象(例如在顯示的時候,將字體、大小等信息傳遞給對象)。

作用:運用共享技術(shù)有效地支持大量細粒度的對象。

內(nèi)部狀態(tài)intrinsic和外部狀態(tài)extrinsic:

1)Flyweight模式中,最重要的是將對象分解成intrinsic和extrinsic兩部分。

2)內(nèi)部狀態(tài):在享元對象內(nèi)部并且不會隨環(huán)境改變而改變的共享部分,可以稱為是享元對象的內(nèi)部狀態(tài)

3)外部狀態(tài):而隨環(huán)境改變而改變的,取決于應用環(huán)境,或是實時數(shù)據(jù),這些不可以共享的東西就是外部狀態(tài)了。

4)內(nèi)部狀態(tài)和外部狀態(tài)之間的區(qū)別:
  在Flyweight模式應用中,通常修改的是外部狀態(tài)屬性,而內(nèi)部狀態(tài)屬性一般都是用于參考或計算時引用。
Flyweight執(zhí)行時所需的狀態(tài)必定是內(nèi)部的或外部的。內(nèi)部狀態(tài)存儲于ConcreteFlyweight對象之中;而外部狀態(tài)則由Client對象存儲或計算。當用戶調(diào)用Flyweight對象的操作時,將該狀態(tài)傳遞給它。

以文字處理軟件為例:

  內(nèi)部狀態(tài)存儲于flyweight中,它包含了獨立于flyweight場景的信息,這些信息使得flyweight可以被共享。如字符代碼,字符大小……

  外部狀態(tài)取決于flyweight場景,并根據(jù)場景而變化,因此不可共享。用戶對象負責在必要的時候?qū)⑼獠繝顟B(tài)傳遞給flyweight,如字符位置,字符顏色……

UML圖:

2016316105111376.png (656×489)

解析:
Flyweight:享元類的基類,定義一個接口,通過這個接口Flyweight可以接受并作用于外部狀態(tài)。

ConcreteFlyweight:實現(xiàn)Flyweight接口, 并為內(nèi)部狀態(tài)( 如果有的話) 增加存儲空間。ConcreteFlyweight對象必須是可共享的。它所存儲的狀態(tài)必須是內(nèi)部的(intrinsic);即,它必須獨立于ConcreteFlyweight對象的場景。

UnsharedConcreteFlyweight:并非所有的Flyweight子類都需要被共享。Flyweight接口使共享成為可能,但它并不強制共享。在Flyweight對象結(jié)構(gòu)的某些層次,UnsharedConcreteFlyweight對象通常將ConcreteFlyweight對象作為子節(jié)點。

FlyweightFactory:

1) 創(chuàng)建并管理Flyweight對象。

2)確保合理地共享Flyweight。當用戶請求一個Flyweight時,F(xiàn)lyweightFactory對象提供一個已創(chuàng)建的實例或者創(chuàng)建一個(如果不存在的話)

Client
1)維持一個對Flyweight的引用。

2)計算或存儲一個(多個)Flyweight的外部狀態(tài)。

分析:
   享元模式可以避免大量非常相似類的開銷。在程序設計中,有時需要生成大量細粒度的類實例來表示數(shù)據(jù)。如果能發(fā)現(xiàn)這些實例數(shù)據(jù)除了幾個參數(shù)外基本都是相同的。有時就能夠大幅度地減少實例化的類的數(shù)量。如果能把那些參數(shù)移到類實例的外面,在方法調(diào)用時將它們傳遞進來,就可以通過共享大幅度地減少單個實例的數(shù)目。

  比如在文檔編輯器的設計過程中,我們?nèi)绻麨闆]有字母創(chuàng)建一個對象的話,系統(tǒng)可能會因為大量的對象而造成存儲開銷的浪費。例如一個字母“a”在文檔中出現(xiàn)了100000次,而實際上我們可以讓這一萬個字母“a”共享一個對象,當然因為在不同的位置可能字母“a”有不同的顯示效果(例如字體和大小等設置不同),在這種情況我們可以為將對象的狀態(tài)分為“外部狀態(tài)”和“內(nèi)部狀態(tài)”,將可以被共享(不會變化)的狀態(tài)作為內(nèi)部狀態(tài)存儲在對象中,而外部對象(例如上面提到的字體、大小等)我們可以在適當?shù)臅r候?qū)⑼獠繉ο笞顬閰?shù)傳遞給對象(例如在顯示的時候,將字體、大小等信息傳遞給對象)。

  Flyweight的內(nèi)部狀態(tài)是用來共享的,F(xiàn)lyweightfactory負責維護一個Flyweight池(存放內(nèi)部狀態(tài)的對象),當客戶端請求一個共享Flyweight時,這個factory首先搜索池中是否已經(jīng)有可適用的,如果有,factory只是簡單返回送出這個對象,否則,創(chuàng)建一個新的對象,加入到池中,再返回送出這個對象.池為重復或可共享的對象、屬性設置一個緩沖,稱為內(nèi)部狀態(tài)。這些內(nèi)部狀態(tài)一般情況下都是不可修改的,也就是在第一個對象、屬性被創(chuàng)建后,就不會去修改了(否則就沒意義了)。

  Flyweight 對對象的內(nèi)部狀態(tài)進行共享,只為每種內(nèi)部狀態(tài)創(chuàng)建一個實例,對內(nèi)部狀態(tài)使用了單例模式。

  用戶不應直接對ConcreteFlyweight類進行實例化,而只能從FlyweightFactory對象得到ConcreteFlyweight對象,這可以保證對它們適當?shù)剡M行共享。

  存儲節(jié)約由以下幾個因素決定:
  1) 因為共享,實例總數(shù)減少的數(shù)目
  2) 對象內(nèi)部狀態(tài)的平均數(shù)目
  3) 外部狀態(tài)是計算的還是存儲的

實現(xiàn)要點
1)享元工廠維護一張享元實例表。

2)享元不可共享的狀態(tài)需要在外部維護。即刪除外部狀態(tài):該模式的可用性在很大程度上取決于是否容易識別外部狀態(tài)并將它從共享對象中刪除。

3)按照需求可以對享元角色進行抽象。

4)管理共享對象:引用計數(shù)和垃圾回收……

何時采用
1)如果一個應用程序使用了大量的對象,而大量的這些對象造成了很大的存儲開銷時就應該考慮使用;

2)還有就是對象的大多數(shù)狀態(tài)可變?yōu)橥獠繝顟B(tài),如果刪除對象的外部狀態(tài),那么可以用相對較少的共享對象取代很多組對象,此時可以考慮所使用享元模式。

3)系統(tǒng)中有大量耗費了大量內(nèi)存的細粒度對象,并且對外界來說這些對沒有任何差別的(或者說經(jīng)過改造后可以是沒有差別的)。

  在文檔編輯器例子中如果一個字符對應一個對象,那么一篇文檔所要容納的對象將是非常的龐大耗費大量的內(nèi)存。而實際組成文檔的字符是有限的,是由這些字符不同的組合和排列得到的。所以需要共享,將基本的字符進行共享,將使得字符對象變得有限。

示例:
享元模式在編輯器系統(tǒng)中大量使用。一個文本編輯器往往會提供很多種字體,而通常的做法就是將每一個字母做成一個享元對象。享元對象的內(nèi)蘊狀態(tài)就是這個字母,而字母在文本中的位置和字模風格等其他信息則是外蘊狀態(tài)。比如,字母a可能出現(xiàn)在文本的很多地方,雖然這些字母a的位置和字模風格不同,但是所有這些地方使用的都是同一個字母對象。這樣一來,字母對象就可以在整個系統(tǒng)中共享。

// Flyweight pattern -- Real World example 


using System;
using System.Collections;

namespace DoFactory.GangOfFour.Flyweight.RealWorld
{

 // MainApp test application 

 class MainApp
 {
  static void Main()
  {
   // Build a document with text 
   string document = "AAZZBBZB";
   char[] chars = document.ToCharArray();

   CharacterFactory f = new CharacterFactory();

   // extrinsic state 
   int pointSize = 10;

   // For each character use a flyweight object 
   foreach (char c in chars)
   {
    pointSize++;
    Character character = f.GetCharacter(c);
    character.Display(pointSize);
   }

   // Wait for user 
   Console.Read();
  }
 }

 // "FlyweightFactory" 

 class CharacterFactory
 {
  private Hashtable characters = new Hashtable();

  public Character GetCharacter(char key)
  {
   // Uses "lazy initialization" 
   Character character = characters[key] as Character;
   if (character == null)
   {
    switch (key)
    {
     case 'A': character = new CharacterA(); break;
     case 'B': character = new CharacterB(); break;
      // 
     case 'Z': character = new CharacterZ(); break;
    }
    characters.Add(key, character);
   }
   return character;
  }
 }

 // "Flyweight" 

 abstract class Character
 {
  protected char symbol;
  protected int width;
  protected int height;
  protected int ascent;
  protected int descent;
  protected int pointSize;

  public abstract void Display(int pointSize);
 }

 // "ConcreteFlyweight" 

 class CharacterA : Character
 {
  // Constructor 
  public CharacterA()
  {
   this.symbol = 'A';
   this.height = 100;
   this.width = 120;
   this.ascent = 70;
   this.descent = 0;
  }

  public override void Display(int pointSize)
  {
   this.pointSize = pointSize;
   Console.WriteLine(this.symbol + 
    " (pointsize " + this.pointSize + ")");
  }
 }

 // "ConcreteFlyweight" 

 class CharacterB : Character
 {
  // Constructor 
  public CharacterB()
  {
   this.symbol = 'B';
   this.height = 100;
   this.width = 140;
   this.ascent = 72;
   this.descent = 0;
  }

  public override void Display(int pointSize)
  {
   this.pointSize = pointSize;
   Console.WriteLine(this.symbol + 
    " (pointsize " + this.pointSize + ")");
  }

 }

 // C, D, E, etc. 

 // "ConcreteFlyweight" 

 class CharacterZ : Character
 {
  // Constructor 
  public CharacterZ()
  {
   this.symbol = 'Z';
   this.height = 100;
   this.width = 100;
   this.ascent = 68;
   this.descent = 0;
  }

  public override void Display(int pointSize)
  {
   this.pointSize = pointSize;
   Console.WriteLine(this.symbol + 
    " (pointsize " + this.pointSize + ")");
  }
 }
}

Output:

2016316105157984.png (748×133)

享元模式的優(yōu)點和缺點

享元模式的優(yōu)點在于它大幅度地降低內(nèi)存中對象的數(shù)量。但是,它做到這一點所付出的代價也是很高的:
享元模式使得系統(tǒng)更加復雜。為了使對象可以共享,需要將一些狀態(tài)外部化,這使得程序的邏輯復雜化。
享元模式將享元對象的狀態(tài)外部化,而讀取外部狀態(tài)使得運行時間稍微變長。

相關(guān)文章

  • 詳解C++ 共享數(shù)據(jù)保護機制

    詳解C++ 共享數(shù)據(jù)保護機制

    這篇文章主要介紹了詳解C++ 共享數(shù)據(jù)保護機制的相關(guān)資料,幫助大家更好的理解和學習使用c++,感興趣的朋友可以了解下
    2021-02-02
  • C語言 如何求兩整數(shù)的最大公約數(shù)與最小公倍數(shù)

    C語言 如何求兩整數(shù)的最大公約數(shù)與最小公倍數(shù)

    這篇文章主要介紹了C語言中如何求兩整數(shù)的最大公約數(shù)與最小公倍數(shù),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • C語言函數(shù)的參數(shù)使用指針

    C語言函數(shù)的參數(shù)使用指針

    這篇文章主要介紹了C語言函數(shù)的參數(shù)使用指針,本文講述了指針在作為函數(shù)參數(shù)時候的使用方法,解析值傳遞和值引用的區(qū)別案例,希望對你有所幫助
    2021-06-06
  • C語言UDP傳輸系統(tǒng)源碼

    C語言UDP傳輸系統(tǒng)源碼

    這篇文章主要為大家分享了C語言UDP傳輸系統(tǒng)的源碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-02-02
  • Windows上使用vs編譯fdk-aac的教程詳解

    Windows上使用vs編譯fdk-aac的教程詳解

    有時需要在Windows上用到fdk-aac,fdk-aac是源碼是cmake的,可以直接轉(zhuǎn)成vs項目,下面就跟隨小編一起學習一下如何在Windows上使用vs編譯fdk-aac吧
    2023-11-11
  • C++ boost scoped_ptr智能指針詳解

    C++ boost scoped_ptr智能指針詳解

    智能指針是一種像指針的C++對象,但它能夠在對象不使用的時候自己銷毀掉。雖然STL提供了auto_ptr,但是由于不能同容器一起使用(不支持拷貝和賦值操作),因此很少有人使用。它是Boost各組件中,應用最為廣泛的一個
    2022-11-11
  • C++多重繼承及多態(tài)性原理實例詳解

    C++多重繼承及多態(tài)性原理實例詳解

    這篇文章主要介紹了C++多重繼承及多態(tài)性原理實例詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-07-07
  • C++稀疏矩陣的各種基本運算并實現(xiàn)加法乘法

    C++稀疏矩陣的各種基本運算并實現(xiàn)加法乘法

    今天小編就為大家分享一篇關(guān)于C++稀疏矩陣的各種基本運算并實現(xiàn)加法乘法,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-02-02
  • C++ LibCurl實現(xiàn)Web指紋識別功能

    C++ LibCurl實現(xiàn)Web指紋識別功能

    Web指紋識別是一種通過分析Web應用程序的特征和元數(shù)據(jù),以確定應用程序所使用的技術(shù)棧和配置的技術(shù),本文將通過C++中LibCurl庫實現(xiàn)簡單是指紋識別功能,感興趣的可以了解下
    2023-11-11
  • C語言使用深度優(yōu)先搜索算法解決迷宮問題(堆棧)

    C語言使用深度優(yōu)先搜索算法解決迷宮問題(堆棧)

    這篇文章主要介紹了C語言使用深度優(yōu)先搜索算法解決迷宮問題,涉及C語言堆棧的使用與深度優(yōu)先算法解決迷宮問題的相關(guān)操作技巧,需要的朋友可以參考下
    2017-09-09

最新評論

贡嘎县| 通道| 同心县| 濮阳县| 阿图什市| 巴楚县| 交口县| 蒙阴县| 建水县| 集贤县| 奉化市| 甘德县| 余庆县| 宁阳县| 邵武市| 调兵山市| 南和县| 汽车| 长武县| 留坝县| 福泉市| 泗水县| 平顺县| 高邮市| 清镇市| 镶黄旗| 乐陵市| 越西县| 双城市| 连州市| 伊宁市| 分宜县| 鹤壁市| 彝良县| 青冈县| 江安县| 左云县| 云和县| 临湘市| 十堰市| 垫江县|