ポリモーフィズムはカップリングを増やす価値がありますか?
-
06-07-2019 - |
質問
C ++の経験を積むために単純化したゲームを書いていますが、ポリモーフィズムがほとんど動作すると感じていますが、動作していません。このゲームでは、Party
はMap
をほぼ直線的に移動しますが、道路でFork
に遭遇することもあります。フォークは(基本的に)std::vector<location*>
です。元々、次のようなコードをgetNext()
メンバー関数にコーディングしていました。
if(!CurrLocation->fork_.empty())
// Loop through forks and show options to the player, go where s/he wants
else
(CurrLocation++)
しかし、次のバリエーションの方が良いのではないかと思っていました:
CurrLocation = CurrLocation->getNext();
Forkは実際にはLocationから派生しており、いくつかの新しい関数location
をオーバーロードしています。ただし、後者の場合、UserInterface::*
(低レベルの構造)は、<!> quot;このバックアップを渡す<!> quot;ではなく、ユーザーにメッセージを提示するものでなければなりません。 <=>を<=>に結合するため、t feelはエレガントです。
あなたの意見は?
解決
すべての問題は、間接レベルを追加することで解決できます。提案されたバリアントを使用し、方向の選択を解決するオブジェクトをgetNextが受け入れることを許可することにより、ロケーションをパーティーから分離します。次に例を示します(未テスト):
class Location;
class IDirectionChooser
{
public:
virtual bool ShouldIGoThisWay(Location & way) = 0;
};
class Location
{
public:
virtual Location * GetNext(IDirectionChooser & chooser)
{
return nextLocation;
}
virtual Describe();
private:
Location * nextLocation;
};
class Fork : public Location
{
public:
virtual Location * GetNext(IDirectionChooser & chooser)
{
for (int i = 0; i < locations.size(); i++)
if (chooser.ShouldIGoThisWay(*locations[i]))
return locations[i];
}
virtual Describe();
private:
vector<Location *> locations;
};
class Party : public IDirectionChooser
{
public:
void Move()
{
currentLocation = currentLocation->GetNext(GetDirectionChooser());
}
virtual IDirectionChooser & GetDirectionChooser() { return *this; }
virtual bool ShouldIGoThisWay(Location & way)
{
way.Describe();
cout << "Do you want to go that way? y/n" << endl;
char ans;
cin >> ans;
return ans == 'y';
}
};
他のヒント
理に適っており、設計を簡素化する限り、ポリモーフィズムを使用する必要があります。それが存在し、派手な名前を持っているという理由だけでそれを使用すべきではありません。設計が単純になる場合は、結合する価値があります。
すべての設計決定の最終目標は、正確さと単純さです。
あなたは自分で問題を見つけたと思いますが、おそらくシステムの残りの部分の知識またはここでいくつかの詳細を確認して解決することができます。
前述のとおり:
- デザインを簡素化するためにポリモーフィズムを使用する必要があります-この場合、多態性はよく見分けられます。
- カップリングに問題があります-再びよく見分けられますが、カップリングは後で問題を引き起こす可能性があります。しかし、これは私に言うことはあなたがいる方法です ポリモーフィズムを適用するのが最善の方法ではない可能性があります。
- インターフェースへのプログラミングにより、システムがどのように組み立てられているかに関する内部の詳細を隠して、結合を減らすことができます。
ポリモーフィズムは、より大きなカップリングには役立たず、別の問題だと思います。
実際、インターフェイスにプログラミングし、制御パターンの一般的な反転に従う場合、結合が少なくなるか、ゼロになります。
あなたの例では、場所がUserInterfaceにどのように結合されているかわかりませんか?
この場合、カップリングは、LocationViewAdapterなど、UserInterfaceとLocationの間の別の抽象化レベルを介して削除できますか?