3

私が長年携わってきたプロジェクトでは、非常に役立つことが証明されているデザイン パターンを徐々に進化させてきました。私は時々それで少し福音的にならなければならないと感じますが、それが誰かの古い帽子の私の​​バージョンであることがわかったら、少し恥ずかしいです. 私は無駄にデザインパターンを掘り下げましたが、それについて話している人に出くわしたことはありませんが、私の検索は網羅的ではありませんでした.

コアとなるアイデアは、一連の定義オブジェクトを管理するブローカー オブジェクトを持つことです。各定義オブジェクトは、いくつかの複雑なプロパティの可能な値を構成します。例として、すべて EngineType を持つ Car、Plane、および Generator クラスがあるとします。Car は独自の EngineType オブジェクトを保存しません。車が持つエンジンの種類を示す何らかの種類の参照キー (整数または文字列 ID など) を保存します。たとえば、WankelEngine などの EngineType のプロパティまたは動作を調べたい場合は、EngineTypeBroker シングルトン オブジェクトに WankelEngine の定義オブジェクトを要求し、それに参照キーを渡します。このオブジェクトは、EngineTypes について知っておくべき興味深いことをすべてカプセル化します。単にプロパティ リストである可能性がありますが、動作が読み込まれる可能性もあります。

したがって、それが促進しているのは一種の共有された疎結合の集約であり、多くの車が WankelEngine を持っている可能性がありますが、WankelEngine 定義オブジェクトは 1 つしかありません (そして、EngineTypeBroker はそのオブジェクトを置き換えることができ、疎結合を強化された実行時のモーフィズムに活用します)。

私が使用するこのパターンのいくつかの要素 (引き続き EngineType を例として使用します):

  1. 指定された値が EngineType の有効な参照キーであるかどうかを判断するための IsEngineType(x) 関数と、参照キーに対応する EngineType 定義オブジェクトを取得するための EngineType(x) 関数が常に存在します。
  2. 特定の EngineType に対して常に複数の形式の参照キーを許可します。常に少なくとも文字列名と定義オブジェクト自体、多くの場合は整数 ID、そして場合によっては EngineType を集約するオブジェクト タイプを許可します。これはデバッグに役立ち、コードをより柔軟にし、私の特定の状況では、古い慣行と比較して多くの下位互換性の問題を緩和します. (このプロジェクトのコンテキストでは、人々がこれをすべて行うために使用する通常の方法は、EngineType が持つ可能性のある各プロパティのハッシュを定義し、参照キーでプロパティを検索することでした。)
  3. 通常、各定義インスタンスは、その定義タイプの汎用クラスのサブクラスです (つまり、WankelEngine は EngineType を継承します)。定義オブジェクトのクラス ファイルは、/Def/EngineType のようなディレクトリに保持されます (つまり、WankelEngine のクラスは /Def/EngineType/WankelEngine になります)。そのため、関連する定義はグループ化され、クラス ファイルは EngineType の構成ファイルに似ていますが、コードを定義する機能があります (通常、構成ファイルにはありません)。

いくつかの自明なサンプル疑似コード:

class Car {

    attribute Name;
    attribute EngineTypeCode;

    object GetEngineTypeDef() {
        return EngineTypeBroker->EngineType(this->GetEngineTypeCode());
    }

    string GetDescription() {
        object def = this->GetEngineTypeDef();
        return "I am a car called " . this->GetName() . ", whose " .
            def->GetEngineTypeName() . " engine can run at " .
            def->GetEngineTypeMaxRPM() . " RPM!";
    }

}

それで、これに名前はありますか?

4

6 に答える 6

2

シングルトンレジストリ

私を信じるかどうか。今朝全く同じことを考えていました。

以前にこのパターンを使用したことがありますが、リファレンスを見つけたことがなく、名前を付ける方法も知りません。

インスタンスがどこかに保存され、キーを使用して取得される、一種の「キー付き」シングルトンだと思います。

最後に使用したのは、さまざまなソースからデータを取得することでした。

私は約50のデータベーステーブルを持っていました(それを10にします)そして、データが表示されるフロントエンドの「テーブル」を持っていますが、データはそれらのソースのいずれかから来る可能性があり、それぞれに異なるロジック(クエリ、結合、キーなど)

このフロント エンドは「構成可能」だったので、どの値が表示され、どの値が表示されないかわかりませんでした。

解決策は、(フロント エンドの) columnName をキーとして取得し、正しいインスタンスを取得して正しいクエリを作成することでした。

これは最初にハッシュ マップにインストールされ、後でデータベース テーブルから取得されました。

コードは次のようになりました。

class DataFetcher {
    abstract Object getData( Object id );
}

class CustomerNameDataFetcher extends DataFetcher {
    Object getData( Object customerId ) { 
        // select name from customer where id = ? 
     }
}

class CompanyAdressDataFetcher extends DataFetcher { 
     Object getData( Object customerId ) { // don't ask why.
          // select name from company , customer where customer.co = company.co and cu = ?  etc.
     }
} 

class ProductColor extends DataFetcher { 
     Object getData( Object x ) { 
     // join from customer to color, to company to season to a bunch of table where id = ? 
}

// And the list goes on.

各サブクラスは異なるロジックを使用しました。

実行時に、ユーザーはビューを構成し、見たいものを選択します。

ユーザーが表示する列を選択したときに、列名と Id を使用してデータをフェッチしました。

DataFetchers はすべて、クラス メソッドの親クラスにインストールされました (これには別のクラスを用意したくなかった)。

class DataFetcher {
    abstract Object getData( Object id );

    private static final Map fetchers = new HashMap();static { 
        fetchers.put("customer.name", new CustomerNameDataFetcher() );
        fetchers.put("company.address", new CompanyAdressDataFetcher () );
        fetchers.put("product.color", new ProductColor () );
        ...
    }
    public static DataFetcher getFetcher( String id ) { 
        return fetchers.get( id );
    }      

}

最後に、フロント エンド テーブルを埋めるために、次のように呼び出します。

疑似コード

 for each row in table 
      for each column in row
          column.text = DataFetcher.getFetcher( column.id ).getData( row.id )
       end
 end

こんな感じですか?それとも、あなたの説明を読み違えていて、私の説明はまったく異なっているのでしょうか。

最後に、これは SingletonRegistry などと呼ばれていると思います。私は(おそらく)あなたが好きで、必要に迫られてこれを作成しました。おそらく、これはよくあるパターンです。

于 2008-12-30T23:09:40.993 に答える
2

私はこれに似たパターンを以前に使用したことがあり、ほとんどの場合ゲームで使用しました。WeaponDefinition クラスと WeaponInstance クラスが必要です (これらの名前とは異なります)。WeaponDefinition クラス (および、さまざまな種類の武器 (近接 vs 発射体など) がある場合は、さまざまなサブクラス) は、その種類の武器 (発射速度、最大弾薬数、名前など) のグローバル データを追跡する責任があり、すべてのロジック。WeaponInstance クラス (およびサブクラス) には、発射シーケンスの現在の状態 (発射速度の比較に使用)、現在の弾薬数、およびポインター (例のようにマネージャー クラスへのキーになる可能性がありますが、パターンの要件ではないようです) を WeaponDefinition に追加します。WeaponInstance には、発砲、リロードなどの関数がたくさんあります。WeaponDefinition インスタンスで適切なメソッドを呼び出し、それ自体を引数として渡すだけです。これは、WeaponDefinition がゲーム世界のすべての戦車/兵士/飛行機で複製されるわけではなく、すべて独自の弾薬数などを持っていることを意味します。

私はそれが何と呼ばれているのかわかりませんし、あなたが話していることとまったく同じかどうかはわかりませんが、近いと思います. それは間違いなく便利です。

于 2008-12-31T00:28:30.863 に答える
1

GoF Builder、Prototype、そしておそらく Featherweight の組み合わせのように思えます。

于 2008-12-30T22:38:22.257 に答える
1

これは、featherweight がシングルトンとして登録される Service Locator に少し似ています。

于 2014-05-07T18:07:59.763 に答える
1

Flyweightの一種のように聞こえます(多くの車がWankelEngineを共有しています). しかし、それはどのように理にかなっていますか?ほとんどの車にはエンジンがありますが、多くの車が同じエンジンのインスタンスを持つことができるのはなぜでしょうか? 彼らはそのようには遠くまで行かないでしょう。それとも、多くの車が VankelEngine タイプのエンジンを搭載しているということですか? より理にかなっているスポーズ。では「WankelEngine定義オブジェクト」は何に使うのでしょうか?そのオブジェクトのフレーバーを構築し、リクエスターに戻すのは Factory ですか? もしそうなら、それは定義オブジェクトのようには聞こえませんが、構築するオブジェクトのパラメーターを取り込んでそのオブジェクトを返す Factory のように聞こえます。

ここには、いくつかの優れた GoF プラクティスが見られます。具体的には、継承ではなく作成しています (私の車にはエンジンがありますが、私の車のエンジンは VankelEngine です)。引用を正確に思い出すことができればいいのですが、それは「継承はカプセル化を破る」と「継承よりも構成を優先する」のようなものです。

これによってどのような問題が解決されるのか興味があります。かなりの複雑さを追加したと思いますが、そのような複雑さの必要性は見られません。多分それは私が理解できないあなたの言語に特有のものです.

GoF の担当者は、パターンをより大きなパターンに合成することについて議論しています。特に MVC は、他の 3 つのパターンの集合体です。そのようなことをしたようですね。

于 2008-12-30T22:57:03.530 に答える
-1

あなたが持っているのは地図、別名辞書です。複数のキーを 1 つのオブジェクトにマップすることで、独自のひねりを加えることができます。

地図である理由:

  • 鍵を預ける
  • キーを使用して、データ構造から値をクエリします。

実装は次の場所にあります。

  • STL (インクルード: マップ)
  • Java (インポート: java.util.Dictionary)
于 2011-12-12T06:00:47.097 に答える