blog

デザインパターン(11) ヘドニック・パターン

オブジェクト指向のアイデアに基づいて設計されたアプリケーションは、同じオブジェクトや表示オブジェクトのインスタンスを大量に必要とするシナリオに遭遇することがあります。例えば、囲碁のゲームで、手を打つた...

Feb 3, 2020 · 4 min. read
シェア

オブジェクト指向の考えに基づいて設計されたアプリケーションでは、同じオブジェクトを大量にシーンに表示したり、シーンのオブジェクトインスタンスを表示したりする必要が生じることがあります。これらの膨大な数のインスタンスは、多くのシステムリソースを消費する可能性が高く、最も直接的なものはメモリです。たとえば、囲碁ゲームをしたい場合、手を打つたびに新しいオブジェクトを作成すると、多くのメモリを消費しますが、実際には駒は黒と白だけで、違いは手の位置だけです。また、アクティブなオブジェクトの数が多いと、また、CPUやグラフィックカードのコンピューティングリソースの多くを占有し、極端な例を取るために、砂漠のシーンのゲームは、ゲームが豊かな視覚効果を持っているようにするために、光と砂の各粒の要件は、異なるレンダリング効果を持っているもちろん、直接新しいも非現実的である異なっています。

ヘドニック・パターン

ヘドニック・パターンは、このようなシナリオに対するソリューションを提供します。すでに存在するオブジェクトを共有することで、作成する必要のあるオブジェクトの数を大幅に減らし、多数の類似オブジェクトのオーバーヘッドを回避し、システムリソースの利用を改善することで、多数のきめ細かいオブジェクトの再利用をサポートします。

UML クラス図:

コードの実装

public abstract class Flyweight
{
 //内部状態
 public string Instrinsic { get; set; }
 //外部状態
 protected string Extrinsic { get; set; }
 public Flyweight(string extrinsic)
 {
 this.Extrinsic = extrinsic;
 }
 //ビジネス・オペレーションを定義する
 public abstract void Operate(int id);
}
public class ConcreteFlyweight : Flyweight
{
 //外部の状態を受け入れる
 public ConcreteFlyweight(String extrinsic) : base(extrinsic)
 {
 }
 //外部状態に基づく論理処理
 public override void Operate(int id)
 {
 Console.WriteLine("Flyweight:" + id);
 }
}
public class UnsharedConcreteFlyweight : Flyweight
{
 public UnsharedConcreteFlyweight(String extrinsic) : base(extrinsic)
 {
 }
 public override void Operate(int id)
 {
 Console.WriteLine("共有しないフライ級:" + id);
 }
}
public class FlyweightFactory
{
 //プールコンテナを定義する
 private static Dictionary<String, Flyweight> pool = new Dictionary<String, Flyweight>();
 //ヘドニック・ファクトリー
 public static Flyweight GetFlyweight(string extrinsic)
 {
 Flyweight flyweight = null;
 if (pool.ContainsKey(extrinsic))
 {
 flyweight = pool[extrinsic];
 Console.Write($" {extrinsic} ");
 }
 else
 {
 flyweight = new ConcreteFlyweight(extrinsic);
 pool.Add(extrinsic, flyweight);
 Console.Write($" {extrinsic} ");
 }
 return flyweight;
 }
}

ヘドニック・パターンの中核は、共有が必要なオブジェクトをキャッシュするためのプール・コンテナです。

内部状態と外部状態このような多数の細かいオブジェクトは似たような性質を持っているため、それらを共有できるようにするためには、これらのオブジェクトに関する情報を内部状態と外部状態の2つに分ける必要があります。

  • 内部状態とは、対象が共有する情報のことで、快楽的な対象の内部に保存され、環境によって変化することはありません;
  • 外部状態とは、環境によって変化し、共有できない状態のこと。例えば、先ほどの囲碁の例で言えば、駒の白と黒の色が内部状態、落ちてくる駒の位置が外部状態です。 内部状態をオブジェクトの本質的な違いとすれば、オブジェクトは2つだけでよく、あとは外部状態の変化と合わせて、すべての駒を表現することができます。

誤解を招きやすい囲碁の例囲碁の例を使うと混乱することがあります:実際には物体は2つしかないのに、どうして同じ物体がAの位置とBの位置に現れるのでしょうか?シュレーディンガーの猫のように、複数の状態を持つことは可能なのでしょうか?実際、ここでいう共有オブジェクトとは、オブジェクトの振る舞いを共有するものです。囲碁のゲームでは、これはキャンバスに描かれた駒のパターンとして理解できます。各駒オブジェクトは駒のパターンを描く振る舞いを持ち、異なる外部状態を設定することで、駒の描画振る舞いがキャンバス上の異なる場所にパターンを描きます。

ヘドニック・パターンのシナリオ

  • システムにはたくさんのオブジェクトがあります。
  • これらのオブジェクトは多くのメモリを消費します。
  • これらのオブジェクトの状態のほとんどは外部化することができます。
  • これらのオブジェクトは、内部状態に応じて多くのグループに分けることができ、オブジェクトから外部オブジェクトを除外する場合は、各グループを単一のオブジェクトに置き換えることができます。
  • このシステムは、見分けがつかないこれらのオブジェクトの同一性には依存しません。

ヘドニック・パターンの長所と短所

バンテージ

  • オブジェクトの作成を大幅に削減し、システムのリソース消費を抑え、効率を向上させます。
  • ヘドニック・パターンは、外部状態と内部状態を抽象化し、外部状態と内部状態を相対的に独立させることで、ヘドニック・オブジェクトを異なる環境で共有することを可能にします。欠点
  • システムの複雑性が増し、外部状態と内部状態を分離する必要があります。外部状態は本質的に内在するものであり、内部状態が変化しても変化してはなりません。
  • オブジェクトを共有可能にするために、ヘドニックパターンはヘドニックオブジェクトの状態を外部化する必要があります。
Read next

ユーザーフォームの入力ボックスのフォーカスに、ちょっとしたエフェクトを追加します。

これはまじめな記事ではないのですが、おそらくユーザー入力フォームを作成する際に、ちょっとした効果を追加したいと思うかもしれません。

Feb 3, 2020 · 2 min read