最近、私は別のプログラマーと、「if」ステートメントでいっぱいの巨大な (1000 行) メソッドをリファクタリングする最善の方法について話し合っていました。
コードは Java で書かれていますが、この問題は C# などの他の言語でも発生する可能性があると思います。
この問題を解決するために、彼は一連の責任パターンを使用することを提案しました。彼は、ベースの「Handler」クラスを持つことを提案しました。次に、「Handler1」、「Handler2」などは「Handler」を拡張します。
次に、ハンドラーには「getSuccessor」メソッドがあり、null (チェーンの最後の場合) またはチェーンの次のハンドラーを返します。
次に、「handleRequest(Request)」関数が Request を処理するか、それをチェーンの次のチェーンに渡します。前の解決策がどれも機能しない場合は、null を返すか、例外をスローします。
チェーンに新しいハンドラを追加するために、コーダーはチェーンの最後の要素に移動し、新しい要素があることを伝えます。何かを行うには、チェーンの最初の要素で handleRequest を呼び出すだけです。
この問題を解決するために、別のアプローチを使用することを提案しました。
前の方法と同じように、「Handler1」、「Handler2」を含む基本「Handler」クラスも必要です。
ただし、「getSuccessor」メソッドはありません。代わりに、ハンドラーのリスト (Vector、ArrayList、またはこの場合に最適なもの) を持つ Collection クラスを使用します。
handleRequest 関数は引き続き存在しますが、呼び出しを次のハンドラーに伝達しません。リクエストを処理するか、null を返すだけです。
リクエストを処理するには、次を使用します
for(Handler handle : handlers){
result = handle.handleRequest(request);
if(result!=null) return result;
}
throw new CouldNotParseRequestException(); //just like in the other approach
または、コードの重複を防ぐために、「parseRequest(request)」メソッドをコレクション クラスに追加することもできます。新しいハンドラーを追加するには、コレクション コンストラクター (または static{} ブロック、または同等のもの) に移動し、単純にコード「addHandler(new Handler3());」を追加します。
このアプローチでは、責任連鎖のどのような利点が欠けていますか? どの方法が最適ですか (最適な方法があると仮定して) ? なんで?各設計方法が引き起こす潜在的なバグや問題は何ですか?
コンテキストが必要な人のために、元のコードは次のようになります。
if(x instanceof Type1)
{
//doSomething1
} else if(x instanceof Type2)
{
//doSomething2
}
//etc.