Flyweightパターンの使用例はありますか?[閉まっている]


21

私はデザインパターンを研究しており、フライウェイトパターンに出くわしました。私は自分のアプリケーションでパターンを使用する機会を探していましたが、その使用方法を理解するのに苦労しています。また、他の人のコードを読んだときに、フライの重量パターンが使用されている兆候は何ですか?

定義によると:

共有を使用して、多数の詳細なオブジェクトを効率的にサポートします。

正しく読んだ場合、辞書とハッシュテーブルはフライウェイトのインスタンスになる可能性がありますが、これは正しいですか?

前もって感謝します。


7
フライウェイトに関するちょっとした逸話:かつて、サードパーティのAPIを使用して大きなExcelファイル(最大50万レコード、100列以上)を作成する必要がありました。セルのスタイルは非常にメモリ集約型になりました。そのため、スタイルが必要になるたびに、同じスタイルが既に存在するかどうかハッシュテーブルがチェックされ、このスタイルへの参照のみが提供されました。この変更により、このエクスポートが可能になりました。私の意見では、これほど多くのデータをExcelで持っているのは狂気です。しかし、コントローラーには保持したい分析マクロがありました。
ファルコン

9
コメント:パターンやオブジェクト指向の本や記事を書く人々が、平均的なプログラマーの現実世界に来て、弁護士スタイルの英語の使用をやめることを願っています!
-NoChance

1
「かつて大きなExcelファイル(最大50万レコード、100列以上)を作成する必要がありました」-これは、一部のトレーダーが作成できるものとはあまり比較されません
;

これらの例のいくつかを読んだ後、私はメモリでデータ圧縮がこのテクニックを実装する絶好の場所になると思います。助けてくれてありがとう!
ジェレミーE

GWTのテーブルセルはフライウェイトです。
user16764

回答:


19

1つの例は、Javaライブラリーです。Javaにはプリミティブ型(たとえばint、32ビット整数)とそれらのラッパー(たとえばInteger、ラップするint)があります。「ボックス」への方法がありますintIntegerとVHS版AN Integerにはint。プリミティブ型はオブジェクトではないため、ラッパーが必要です。したがって、たとえば、Mapsのキーとして使用したり、sに配置したりすることはできませんCollection

ボクシングメソッドは、-128〜127の値にInteger対応するsの種類のキャッシュとしてフライウェイトオブジェクトの配列を使用しintます。これらは、キーとして使用されるかコレクションに配置される可能性が最も高い値であるため、割り当てとメモリ使用量が削減されます。(Integer値0が浮動することを表す5000000が存在する場合、フライウェイトインスタンスを再利用するのに5000000倍のメモリを使用します)。



1
C#の文字列のインターンプールは、フライウェイトパターンのもう1つの正しい例ですか?
ジェレミーE

1
@ジェレミーE:はい、私の意見では、フライウェイトパターンのアプリケーションにストリングを呼び出すことができます。
ファルコン

Objective-Cのタグ付きポインターは、これを極端なものにします。56ビットまでのボックス化された整数、および6文字までの多くの文字列はオブジェクトとしても割り当てられませんが、すべての情報はオブジェクトポインター自体にパックされます。
-gnasher729

9

グラフィック。通常、ラスターイメージ(ほとんどの消費者レベルのコンピューターグラフィックスのバックボーン)はCPUが安くなりますが、使用するにはメモリが高価です(メモリは安価ですがCPUは高価なため、問題ありません)。大きなラスターUI(Windows GUIアプリのアイコンからワードプロセッサのフォントの文字、3Dゲームの表面のテクスチャまで)をレンダリングする際に、そのラスターイメージを何度も繰り返す場合は、多くの意味があります。イメージを一度メモリにロードし、作成するのに安価で、それ自体が多くのメモリを消費しない非常に単純なオブジェクトを使用して、単純にそれをポイントします。スプライトは、単に画像が表示されるグラフィカル空間のポイントであり、3Dポイントと、使用する画像の最初のピクセルへのメモリポインターです。使用するスプライトイメージファイルの部分の寸法も含まれている場合があります。グラフィカル用語またはメモリ用語で。この情報はすべて変更するのに非常に安価です。たとえば、画像またはスプライトの位置を変更します。毎回新しい画像をロードせずに実行できるため、基になるプログラムのパフォーマンスが大幅に向上し、適切な部分を操作および表示できます完全なUI「シーン」をレンダリングする適切な画像。


3

CharacterSmalltalkのASCII範囲インスタンスはフライウェイトです。

のようなものを評価するとCharacter space、次をCharacter class >> #value:実行します。

value: anInteger 
    "Answer the Character whose value is anInteger."

    anInteger > 255 ifTrue: [^self basicNew setValue: anInteger].
    ^ CharacterTable at: anInteger + 1.

クラス変数CharacterTableは次のように初期化されます。

initialize
    "Create the table of unique Characters, and DigitsValues."
    "Character initializeClassificationTable"

    CharacterTable ifNil: [
        "Initialize only once to ensure that byte characters are unique"
        CharacterTable := Array new: 256.
        1 to: 256 do: [:i | CharacterTable
            at: i
            put: (self basicNew setValue: i - 1)]].
    self initializeDigitValues

そのため、文字列を作成すると、ASCII範囲CharactersはCharacterTable毎回新しく作成されるのではなく、そこから取得されます。


3

flyweightパターンを使用する目的は、不要なオブジェクトの初期化を回避し、スペースを節約することです。GOFで定義されているように、オブジェクトには2つの状態、内在状態と外在状態があります。

  • 固有の状態:フライウェイトに保存されます。フライウェイトコンテキストに依存しない情報で構成されているため、共有可能になります。
  • 外因性状態:フライウェイトのコンテキストに依存し、変化するため、共有できません。クライアントオブジェクトは、必要に応じて外部状態をフライウェイトに渡す役割を果たします。

各列にテキストのすべての行が含まれ、行に文字を含めることができる単純なテキストエディターアプリケーションを開発するとします。

ここでのジレンマは、Characterクラスの設計方法です。char c文字クラス内には、メイン(固有状態)オブジェクトであるべきです。ただし、charにはFontおよびSize(外部状態)を含めることができます。したがって、その外部状態をRow(クライアント)に保存し、必要なときにアクセスする必要があります。この目的のために、フォントとサイズを保存する2つのリストが作成されます。

Flyweightパターンに従うことで、Characterは再利用可能になり、すべてのASCIIシンボル(Characterオブジェクト)を含むオブジェクトの特定のリスト(フライウェイトプール)からオブジェクトが参照されます。

ここに視覚的に説明したものがあります:

ここに画像の説明を入力してください

「hello」を印刷Characterするには、5つではなく4つのオブジェクトのみが必要です。フォントが変更されると、新しいオブジェクトは必要ありません。Characterクラスに外部状態を保存していた場合、これは不可能になることに注意してください。たとえば、

class Character
{
    char c;
    int Size;
    Font font;

    ....
}

このパターンを大規模なデータセットに適用すると、アプリケーションのメモリの複雑さとオブジェクトの再利用性が大幅に最適化されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.