複数のサブクラス(Animal
/Dog
)によって継承されたスーパークラスBird
について考えます。そのインスタンス化では、オブジェクトにはローカルの状態と動作があります。
wiki さんのコメント:
戦略パターン
- アルゴリズムのファミリーを定義し、
- 各アルゴリズムをカプセル化し、
- アルゴリズムをそのファミリ内で交換可能にします。
要件でスーパークラスAnimal
に新しい動作(fly()
)を追加する必要がある場合は、戦略パターンを使用して、アルゴリズムの新しいファミリを作成します(CantFly
/ItFly
)およびこれらのアルゴリズムをsetFlyingAbility()
/tryToFly()
にカプセル化して、既存のクラス階層のコード変更を最小限に抑え、以下の変更を加えます。
ここで、ItFyls
とCantFly
は、サブクラス(fly
/Dog
)で互換的に使用される新しい動作(Bird
)のアルゴリズムのファミリーです。 、以下のコード変更
タイプの関連付けCompositionは、cruxで、以下に示すスーパー/サブクラスの関係でコードの変更を最小限に抑えることにより、スーパークラスに新しい動作を追加するのに役立ちます。
_class Animal{
....
Flys flyingType;
....
public String tryToFly(){
return flyingType.fly();
}
public void setFlyingAbility(Flys newFlyType){
flyingType = newFlyType;
}
}
_
質問:
スーパークラス(Animal
)に新しい動作(fly()
)を追加するには、戦略パターンにすべてのサブクラス(Dog
/Bird
)コンストラクタの変更が含まれますか?サブクラスの変更は回避できますか?
ストラテジーパターンの実装は問題ありませんが、ストラテジーパターンが解決している問題を適切に説明している例ではないと思います。
並べ替えを検討してください。比較可能な項目の配列を前提として、さまざまなソートアルゴリズム(または「戦略」)の中から選択します。戦略パターンの一般的な使用例の1つは、たとえば最初のアルゴリズムが終了するまでアルゴリズムを並行して実行するために使用されます。データベースには、最適化フェーズ中に、クエリを実行する最も効率的な方法を見つけるための同様のアプローチがあります。
選択したfly()
戦略は、入力が犬であるか鳥であるかに依存するため、動物から継承するDog/BirdのOOアナロジーはこれに完全には適合しません。
あなたの状況により適しているのは、仮想関数のアイデアです。このような場合、基本クラスのAnimalは関数のシグネチャを宣言し、実装を継承クラスに任せます。
(動物の)既存のクラス階層があり、コードをさらにSOLID(この場合は具体的にはSRPおよびOCPに準拠)にしようとします。次に、リファクタリングによりすべてのコンストラクターを操作する必要が生じます。階層内-しかしそれはごく普通のことです非ソリッドクラス階層をよりソリッドにする場合、ここには特定のアプローチを行うための絶対的なnothingがあります。これは「戦略」です。本当の理由は、より複雑なコードベースをリファクタリングすることは、より単純なコードベースをリファクタリングするよりも多くの労力を必要とすることです-私見はそれほど驚くことではありません!
「Strategy」パターンには、特定の戦略サブクラスを選択または変更する必要があるプログラム内の1つ以上の場所が常に必要です(実行時に変更される場合もあれば、変更されない場合もあります)。これはビジネスロジックの一部であり、「正しい」場所はケースに依存します。単純なコンテキスト(クラス階層のないテストクラスなど)に導入された場合、通常、クラス階層のようなより複雑なコンテキストに導入された場合よりも、変更する必要のあることが少なくなります。ただし、これの理由はコンテキストの複雑さであり、パターンではありません。
この特定の例では、さまざまな動物のコンストラクター-関連付けDog - CantFly
、Bird - ItFlys
はどこかにある必要があり、正しい戦略は動物の種類、一般的な知識によって選択でき、各オブジェクトの有効期間中に変更されないため、コンストラクターはそれを実装するのに最悪の場所ではありません。
したがって、はい、このコードをさらに作成するSOLIDには、コンストラクタの変更が含まれますパターンをコードに導入するときに、それ以下、それ以上(実際のコードでは、おそらく、パターンを導入するために、Animalクラス階層でさらに多くの要素をリファクタリングする必要があります。このようなリファクタリングのポイントは、コードの変更beforeを回避しないことではありません導入されましたが、後です。