Flyweight は、 構造に関するデザインパターンの一つで、 メモリー消費量を低く抑えることで、 プログラムが膨大な数のオブジェクトを支えることができるようにします。
複数のオブジェクト間でオブジェクトの状態の一部を共有することにより、 これを実現します。 つまり、 Flyweight は、 異なるオブジェクトによって使われる同じデータをキャッシュすることにより、 RAM を節約します。
概念的な例
Counter-Strike (反撃) というゲームでは、 テロリストと反テロリストは、 それぞれ違う種類の服を着ています。 話を簡単にするため、 テロリストと反テロリストには、 それぞれ 1 種類の服しかないとしましょう。 以下に示すように、 服オブジェクトは、 プレーヤー・オブジェクトに埋め込まれています。
プレーヤーの構造体は、 以下の通りです。 服 (dress) オブジェクトは、 プレーヤーの構造体に埋め込まれています:
テロリストが 5 人、 反テロリストが 5 人、 全員でプレーヤーが 10 人いるとします。 服に関しては、 二つの扱い方があります。
-
10 人のプレーヤーのそれぞれが 1 個ずつ異なる服オブジェクトを作成し、 それを埋め込みます。 全部で 10 個の服オブジェクトが作成されます。
-
服オブジェクトを 2 個作成:
- テロリストの服オブジェクト一つ: これを、 テロリスト 5 人で共有します。
- 反テロリストの服オブジェクト一つ: これを、 反テロリスト 5 人で共有します。
一つ目の方法では、 全部で 10 個の服オブジェクトが作成されるのに対し、 二つ目の方法では、 たった 2 個の服オブジェクトが作成されます。 二つ目の方法が、 Flyweight デザインパターンです。 作成された 2 個の服オブジェクトのことを、 フライウェイト・オブジェクトと呼びます。
Flyweight パターンでは、 共通の部分を取り出し、 フライウェイト・オブジェクトを作成します。 これらのフライウェイト・オブジェクト (服) は、 複数のオブジェクト (プレーヤー) で共有します。 これは、 ドレス・オブジェクトの数を大幅に削減します。 この利点は、 もしもっと多数のプレーヤーを作成したとしても、 たった 2 個の服オブジェクトだけで十分だということです。
Flyweight パターンでは、 フライウェイト・オブジェクトは、 マップ・フィールドに保存します。 フライウェイト・オブジェクトを共有するオブジェクトが作成されると、 フライウェイト・オブジェクトはマップから取得します。
このお膳立てのどの部分が内因的状態で、 どれが外因的状態かを見てみましょう:
dressFactory.go: フライウェイト・ファクトリー
dress.go: フライウェイト・インターフェース
terroristDress.go: 具象フライウェイト・オブジェクト
counterTerroristDress.go: 具象フライウェイト・オブジェクト
player.go: コンテキスト
game.go: クライアント・コード
main.go: クライアント・コード
output.txt: 実行結果