でブログ記事のこのシリーズ、エリックリッペルトは、ウィザードとの例として、戦士を使用して、オブジェクト指向設計における問題点を説明します。
abstract class Weapon { }
sealed class Staff : Weapon { }
sealed class Sword : Weapon { }
abstract class Player
{
public Weapon Weapon { get; set; }
}
sealed class Wizard : Player { }
sealed class Warrior : Player { }
次に、いくつかのルールを追加します。
- 戦士は剣しか使用できません。
- ウィザードはスタッフのみを使用できます。
次に、C#型システムを使用してこれらのルールを適用しようとすると発生する問題(たとえばWizard
、ウィザードがスタッフのみを使用できることをクラスに責任を持たせるなど)を示します。Liskov置換原則に違反したり、ランタイム例外のリスクを冒したり、拡張が困難なコードを作成したりする。
彼が思いついた解決策は、Playerクラスによって検証が行われないことです。状態の追跡にのみ使用されます。次に、プレイヤーに武器を与える代わりに:
player.Weapon = new Sword();
状態はCommand
s によって、sに従って変更されRule
ます。
... 2つのゲーム状態オブジェクト(a とa)を取る
Command
と呼ばれるオブジェクトを作成します。ユーザーがシステムにコマンドを発行すると、「このウィザードはその剣を振るう必要があります」と、一連のsを生成するsのセットのコンテキストでそのコマンドが評価されます。私たちは、1持っているプレイヤーの試みは、武器を振るうする際、効果は既存の武器は、存在する場合、廃棄され、新たな武器がプレイヤーの武器になることであると述べています。最初のルールを強化する別のルールがあります。つまり、ウィザードが剣を振るうとき、最初のルールの効果は適用されません。Wield
Player
Weapon
Rule
Effect
Rule
私はこのアイデアを原則として気に入っていますが、実際にどのように使用されるかについて懸念があります。
何も回避からの現像を防ぐように思わないCommands
とRule
簡単に設定することで、秒Weapon
にPlayer
。Weapon
プロパティがアクセスできる必要がありWield
、それを行うことができないので、コマンドprivate set
。
それで、開発者がこれを行うのを妨げているものは何ですか?彼らは覚えていないだけでいいですか?