1

私はC++を使用して小さなプロジェクトに取り組んでおり(この質問は言語に依存しないと見なされる可能性があります)、可能な限り効率的でカプセル化されるようにプログラムを作成しようとしています。私は独学で経験の浅いプログラマーですが、インターフェースとOOPプラクティスの使用に関しては自分自身に良い習慣を教えようとしています。別のクラスのサブシステムとして機能しているオブジェクトのメソッドにアクセスする場合、主に典型的な「ベスト」プラクティスに関心があります。

まず、私が何を意味するのかを説明しましょう:

のインスタンスは、のプライベートサブシステムをClassGame使用して2Dスプライトイメージをレンダリングしたいと考えています。のインターフェースにのみアクセスでき、ClassEngineのサブシステム(抽象化レイヤーの背後)であると想定されています。ClassRendererClassEngineClassGameClassEngineClassRenderer

私の質問は、ClassGameオブジェクトがClassRendererの機能を間接的に利用しながら、高速で抽象化レイヤーの背後にある方法に基づいています。レッスンや他の人のコード例で見たものから、これを行うには2つの基本的な方法があるようです。

  1. OOP設計に関する一連のオンライン講義で私が学んだ最初の方法は、1つのクラスにタスクをそのプライベートメンバーオブジェクトに内部的に委任させることでした。[この例では、ClassGameはClassEngineに属するメソッドを呼び出し、ClassEngineはそのメソッドの1つを呼び出すことにより、その要求をClassRendererサブシステムに「密かに」渡します。]関数呼び出しの「デイジーチェーン」の一種。これは私には理にかなっていますが、いくつかの代替オプションよりも遅いようです。

  2. 他の人のコードで見たもう1つの方法は、特定のサブシステムの場所への参照またはポインターを返すアクセサーメソッドを使用することです。[したがって、ClassGameは、ClassRendererサブシステムを構成するオブジェクトへの参照/ポインターを返すClassEngineの単純なメソッドを呼び出します]。このルートは私には便利に思えますが、プライベートメンバーをより大きなクラスのサブコンポーネントとして機能させるという意味も排除されているようです。もちろん、これは、独立したサブシステムごとに1つのgetter関数を簡単に記述できるため、特定のタスクを単純に渡す「無意識の」関数をはるかに少なく作成することも意味します。

速度とパフォーマンスも考慮しながら、オブジェクト指向設計のさまざまな重要な側面(抽象化、カプセル化、モジュール性、使いやすさ、拡張性など)を考慮すると、タスクをサブコンポーネントに委任するために第1または第2のタイプの方法を使用する方が適切です。 ?

4

2 に答える 2

3

「デザインパターンの説明」という本は、ブリッジパターンに関する章で非常によく似た問題について説明しています。どうやらこの章はオンラインで無料で入手できます

私はあなたがそれを読むことをお勧めします:)

タイプ1のアプローチはOOPブリッジパターンに最も似ていると思います。

タイプ2、ハンドルを内部データに戻すことは、一般的に避けるべきものです。

于 2012-12-15T12:31:26.237 に答える
1

やりたいことをする方法はたくさんありますが、それは実際にはコンテキストによって異なります(たとえば、プロジェクトの大きさ、他のプロジェクトでの再利用を期待する量など)。

ゲーム、エンジン、レンダラーの3つのクラスがあります。どちらのソリューションも、ゲームをエンジンのインターフェースにコミットさせます。2番目のソリューションも、ゲームをレンダラーのインターフェイスにコミットさせます。明らかに、使用するインターフェースが多いほど、インターフェースが変更された場合に変更する必要があります。

3番目のオプションはどうですか:ゲームはレンダリングに関して何が必要かを知っているので、それらの要件を説明する抽象クラスを作成できます。これが、ゲームがコミットする唯一のインターフェースになります。このインターフェースをAbstractGameRendererと呼びましょう。

これをシステムの残りの部分に結び付けるには、やはり多くの方法があります。1つのオプションは次のとおりです。1。既存のRendererクラスを使用してこの抽象インターフェースを実装します。したがって、Rendererを使用し、AbstractGameRendererインターフェイスを実装するクラスGameRendererがあります。2.エンジンは、GameオブジェクトとGameRendererオブジェクトの両方を作成します。3.エンジンはGameRendererオブジェクトをGameオブジェクトに渡します(AbstractGameRendererへのポインターを使用)。

結果:ゲームは、必要な処理を実行するレンダラーを使用できます。それがどこから来たのか、どのようにレンダリングされたのか、誰がそれを所有しているのかはわかりません-何もありません。GameRendererは特定の実装ですが、他の実装(他のレンダラーを使用)は後で作成できます。エンジンは「すべてを知っています」(しかし、それは許容できるかもしれません)。

後で、ゲームのロジックを取得して、別のゲームのミニゲームとして使用する必要があります。適切なGameRendererを作成し(AbstractGameRendererを実装)、それをGameオブジェクトに渡すだけです。Gameオブジェクトは、それが別のゲーム、別のエンジン、別のレンダラーであることを気にしません-それも知りません。

重要なのは、設計上の問題には多くの解決策があるということです。この提案は適切または受け入れられない可能性があります。あるいは、まさにあなたが必要としているものかもしれません。私が従おうとしている原則は次のとおりです。1。制御できないインターフェースにコミットしないようにします(変更した場合は変更する必要があります)2。後で発生する痛みを今すぐ防ぐようにします

私の例では、ゲームなどの大きなコンポーネントを変更するよりも、レンダラーが変更された場合にGameRendererを変更する方が苦痛が少ないと想定しています。しかし、盲目的にパターンに従うよりも、原則に固執する(そして痛みを最小限に抑える)方が良いです。

于 2012-12-15T13:20:22.280 に答える