0

私は現在、私がしばらく経験してきた繰り返しの問題に対する「決定的な」解決策(つまり、OOPの教訓に準拠した効率的な解決策を見つけること)を見つけようとしています:私のさまざまな部分での共有データの問題コード。

ここでは MVC フレームワークを使用していないことに注意してください。データ クラスをモデルとして、表示クラスをビューとして参照しているだけです (適切な名前であり、MVC パターンとは何の関係もないため、人々は MVC パターンが「作成」される前にビューとモデルを作成しました。 )。

ここに私の問題があります。かなり拡張されたデータ (ゲームなど) を使用するアプリケーションを作成するときはいつでも、ロジック (動き、衝突など) を分離し、2 つのクラスに表示しようとします。しかし、その後、私は問題に出くわしました:異なるクラス間でデータ、参照、またはその他のものを複製することなく、ロジッククラスに格納されたデータをビュークラスの対応する表示オブジェクトに「バインド」する方法は?

基本的な例を見てみましょう:

  • 「EntityData」オブジェクトのベクターを保持するMyLogicClassがあります(それぞれに位置、サイズ、さまざまな状態、アイテムのロジックを処理するためのすべてがあります)

  • そして、MyLogicClass にある各 EntityData のスプライトを作成して表示し、ゲーム ループで更新された後にスプライトを移動させる MyViewClass があります。

最初に頭に浮かぶのは、各データ要素内に対応するビューを格納することです。これにより、Vector をループして項目ロジックを更新し、それに応じてビューを更新できます。しかし、これにより、MyViewClass 内に MyLogicClass 参照を保持する必要があり、エンティティ データをターゲットにできることを確認して、2 つのクラスを結合する必要があります (これはやりたくないことです)。

一方、データ モデル (ID パラメータを持つ MyLogicClass の EntityData オブジェクト) とビュー クラス (元のエンティティ データ ID への参照を保持するスプライト) の両方で、ID を持つ各エンティティのソリューションがあります。しかし、データ モデルで強制的にループする特定のエンティティをターゲットにしたい場合は、ビューで関連するスプライトを見つけるためにもう一度ループします。このソリューションにより、データとビューを疎結合することができますが、何百もの要素をフレームごとに 2 回ループする (発生する可能性があります!) のは、パフォーマンスが最適化されていないように思えます。

私はこの問題全体を、それに値するよりもはるかに重要視しているかもしれませんが、私はそのことに何度も遭遇しており、それについて私以外の見解を持ちたいと思っています.

このような問題に対するアドバイス/解決策はありますか?

そのような場合に私が認識していない可能性のある他のデータ形式/階層はありますか?

4

2 に答える 2

1

私が行ったことは、イベントとイベントリスナーを使用してそれらを「リンク」することです。「モデル パーツ」に、「表示パーツ」がキャッチしてレンダリング/更新する特定のイベントをスローさせます。

これにより、特定のイベントをリッスンし、そのようにエラーチェックするテストコードを作成することで、いくつかのテストを構造化できることがわかりました。私のコードはまだ分離されており、それ自体でテスト可能です。適切な値で適切なイベントがスローされていることをトリガーして確認することで、「モデル」をテストできます。同様に、問題があるかどうかを確認するために「ディスプレイ」でキャッチできるプリセット イベントをスローするテスト コードを書くこともできます。

すべてが機能したら、同じイベントリスナーを再利用して「相互」にリンクします。

後で、「コントローラー」(ユーザー入力) が「モデル」パーツを操作し、イベントが「ディスプレイ」にスローされてレンダリング/更新されます。

これが「正しい」か、mvcパターンに従うという点でそうでないかはわかりません。また、これらの種類のことについて正式な知識もありません。他の方の詳しい方の意見も聞きたいです。

于 2012-11-17T10:24:00.493 に答える
0

多分あなたは問題を考えすぎていると思います。私は時々これをします。

ビュー クラスには明らかにモデルへのある種のリンクが必要であり、イベントはそれを行うための優れた方法です。アイデアを提供するために、ここに骨の折れる何かがあります。

 // Model class
 package
 {
    class MyModel extends EventDispatcher
    {
        // you can make them public but that would 
        // be against some oop practices. so private it is
        private var m_position:Vector2D; 

        MyModel(){}

        // one way of doing getters/getters
        // example: theModel.SetPosition(something);
        public function GetPosition():Vector2D { return m_position; }
        public function SetPosition(value:Vector2D):void 
        { 
            m_position = value; 
            ModelChanged();
        }

        // the other way
        // sample: theModel.position = something;
        public function get position():Vector2D {return m_position; }
        public function set position(value:Vector2D):void 
        { 
            m_position = value; 
            ModelChanged();
        }

        private function ModelChanged():void
        {
            dispatchEvent(new Event(Event.CHANGE));
        }
    }
}


// now for our view.
package
{
    class MyView extends Sprite // or whatever
    {
        private var model:MyModel;

        MyView(model:MyModel)
        {
            this.model = model;

            model.addEventListener(Event.CHANGE, handleModelChanged);

            // fire off an event to set the initial position.
            handleModelChanged(NULL);
        }

        private function handleModelChanged(evt:Event):void
        {
            x = model.position.x;
            y = model.position.y;
            // etc etc etc.
        }
    }
}

とにかく、モデルファイルにロジックを含める場合は、セッターは必要ありません。また、モデルの外部で何も変更する必要がない場合は、セッターの理由はありません。ただし、ゲッターは必要です。

これにより、モデルがビューから分離され、任意のビューを好きなように記述でき、提供する必要があるのは、モデルが変更されたときのハンドラーだけです。ビューが必要とするデータを getter で公開するだけです。

モデルをループするだけで、モデルが変更されるとイベントが発生し、リッスンしているビューが更新されます。

私が何も見逃していなかったことを願っています。それはあなたが何を望んでいたかを説明しています。

編集:追加するのを忘れていました。更新機能のようなものを使用している場合、「ModelChanged()」をあちこちに配置する必要はありません。更新するだけで、終了したらイベントを開始します。

于 2012-11-17T19:15:03.617 に答える