次のクラス階層を想像してみてください。
interface IRules
{
void NotifyPickup(object pickedUp);
void NotifyDeath();
void NotifyDamage();
}
class CaptureTheFlag : IRules
{
public void NotifyPickup(Pickup pickedUp)
{
if(pickedUp is Flag)
GameOver();
}
public void NotifyDeath()
{
}
public void NotifyDamage()
{
}
}
class DeathMatch : IRules
{
public void NotifyPickup(Pickup pickedUp)
{
points++;
}
public void NotifyDeath()
{
lives--;
}
public void NotifyDamage()
{
}
}
class GameWorld
{
IRules gameMode;
public Main(IRules gameMode)
{
this.gameMode = gameMode;
}
object[] worldObjects;
public void GameLoop()
{
foreach(object obj in worldObjects)
{
// This call may have a bunch of sideeffects, like getting a pickup
// Or a player dying
// Or damage being taken
// Different game modes are interested in different events / statistics.
obj.Update();
// Stuff happens...
gameMode.NotifyDamage();
// Stuff happens...
gameMode.NotifyDeath();
}
}
}
だからここに私はNotify*関数を含むインターフェースを持っています。これらはコールバックです。さまざまなゲームモードが、ゲームのさまざまなイベントに関心を持っています。これらのイベントはworldObjects配列に埋め込まれているため、これらのイベントを作成する具象オブジェクトにアクセスすることは実際には不可能です。ゲームに新しいゲームモードを追加していると想像してください。IRulesインターフェースは非常に肥大化し、ゲームモードが関心を持つ可能性のあるすべてのものが含まれ、ほとんどの呼び出しはスタブされます!どうすればこれを防ぐことができますか?
編集2:具体的な例