数週間前、私は Globo Player のソリューションに取り組みました。そこでは、実行中にソフトウェアの特定の動作をアクティブ化および非アクティブ化する必要がありました。このタイプのニーズは、一般的に if-else や switch などの連鎖条件を使用して解決されますが、このアプローチは常に理想的であるとは限りません。
この記事では、この課題を完全に満たし、さまざまなプログラミング シナリオに適用できるソリューションを紹介します。
あなたが未知の目的地に到着したところだと想像してください。空港を出るとき、ホテルに行くにはいくつかの選択肢があります。最も安価な方法は自転車をレンタルすることですが、これには時間がかかります。バスを利用すると少し高くなりますが、より早く安全に到着します。最後に、レンタカーを借りるのが最も早いオプションですが、最も高価でもあります。
この状況で最も重要な点は、選択した戦略に関係なく、最終的な目的は同じである、つまりホテルに到着するということを理解することです。
このアナロジーはソフトウェア開発にも適用できます。異なるプロセスが同じ目的を達成しようとするシナリオに対処する場合、戦略設計パターンを使用すると役立ちます。
当座、普通、またはプレミアムなど、顧客の口座タイプに基づいて手数料を計算できる銀行システムを開発する必要があると想像してください。これらの計算は実行時に実行する必要があり、コード フローを適切な計算に正しく導く実装が必要です。
原則として、一般的なアプローチは、連鎖した条件文の単純な構造を使用して、問題を迅速かつ機能的に解決することです。
class Banco { calcularTaxa(tipoConta, valor) { if (tipoConta === "corrente") { return valor * 0.02; // 2% de taxa } else if (tipoConta === "poupanca") { return valor * 0.01; // 1% de taxa } else if (tipoConta === "premium") { return valor * 0.005; // 0,5% de taxa } else { throw new Error("Tipo de conta não suportado."); } } } const banco = new Banco(); const taxa = banco.calcularTaxa("corrente", 1000); // Exemplo: R00 console.log(`A taxa para sua conta é: R$${taxa}`);
このソリューションは単純なシナリオではうまく機能しますが、銀行が将来さらに 5 つの口座タイプを追加する必要がある場合はどうなりますか?
calcularTaxa(tipoConta, valor) { if (tipoConta === "corrente") { return valor * 0.02; // 2% de taxa } else if (tipoConta === "poupanca") { return valor * 0.01; // 1% de taxa } else if (tipoConta === "premium") { return valor * 0.005; // 0,5% de taxa } else if (tipoConta === "estudante") { return valor * 0.001; // 0,1% de taxa } else if (tipoConta === "empresarial") { return valor * 0.03; // 3% de taxa } else if (tipoConta === "internacional") { return valor * 0.04 + 10; // 4% + taxa fixa de R } else if (tipoConta === "digital") { return valor * 0.008; // 0,8% de taxa } else if (tipoConta === "exclusiva") { return valor * 0.002; // 0,2% de taxa } else { throw new Error("Tipo de conta inválido!"); } }
ここで、コードに重大な制限が現れ始めます。このアプローチの問題を調べてみましょう:
1.スケーラビリティが低い
新しいアカウント タイプを追加する必要があるたびに、calculateRate メソッドを変更する必要があります。これにより、条件文の数が継続的に増加し、コードがより複雑になり、管理が難しくなります。
2.高い依存性
レート計算ロジックは、calculateRate メソッドに完全に結合されています。ある種類のアカウントに変更を加えると、他の種類のアカウントに誤って影響を与える可能性があり、バグが発生するリスクが高まります。
3.コードの繰り返し
金額 * 手数料などの同様のスニペットは、アカウントの種類ごとに複製されます。これはコードの再利用を減らし、DRY (同じことを繰り返さない) 原則に違反します。
次のステップでは、戦略パターンがこれらの問題をどのように解決し、よりクリーンでスケーラブルなモジュール化されたコードを促進できるかを見ていきます。
上記の問題を回避するために、ソフトウェアでは各アカウント タイプを独立したエンティティとして扱います。これは、アカウントの種類ごとに特定の料金計算があり、将来のその他の関連する動作が発生する可能性があるためです。
すべての操作を解決する CalculateRate メソッドを含む Bank クラスを作成する代わりに、口座の種類ごとにクラスを作成しましょう。
class Banco { calcularTaxa(tipoConta, valor) { if (tipoConta === "corrente") { return valor * 0.02; // 2% de taxa } else if (tipoConta === "poupanca") { return valor * 0.01; // 1% de taxa } else if (tipoConta === "premium") { return valor * 0.005; // 0,5% de taxa } else { throw new Error("Tipo de conta não suportado."); } } } const banco = new Banco(); const taxa = banco.calcularTaxa("corrente", 1000); // Exemplo: R00 console.log(`A taxa para sua conta é: R$${taxa}`);
これにより、各計算操作がアカウント タイプの特定の範囲内に維持されることが保証されます。これで、各タイプのアカウントに焦点を当てた分離された動作が得られました。
しかし、目的のアカウント選択はどこにあるのでしょうか?
calcularTaxa(tipoConta, valor) { if (tipoConta === "corrente") { return valor * 0.02; // 2% de taxa } else if (tipoConta === "poupanca") { return valor * 0.01; // 1% de taxa } else if (tipoConta === "premium") { return valor * 0.005; // 0,5% de taxa } else if (tipoConta === "estudante") { return valor * 0.001; // 0,1% de taxa } else if (tipoConta === "empresarial") { return valor * 0.03; // 3% de taxa } else if (tipoConta === "internacional") { return valor * 0.04 + 10; // 4% + taxa fixa de R } else if (tipoConta === "digital") { return valor * 0.008; // 0,8% de taxa } else if (tipoConta === "exclusiva") { return valor * 0.002; // 0,2% de taxa } else { throw new Error("Tipo de conta inválido!"); } }
連鎖した意思決定構造 (if-else) を作成する代わりに、Bank クラスのコンストラクターでアカウント、ストラテジーを渡すことを選択したことに注意してください。これにより、setConta メソッドは実行時に銀行をインスタンス化するときに目的の口座タイプを選択できるようになります。レートの計算は this.conta.calcularTaxa(valor) を通じて実行されます。
class ContaCorrente { calcularTaxa(valor) { return valor * 0.02; // 2% de taxa } } class ContaPoupanca { calcularTaxa(valor) { return valor * 0.01; // 1% de taxa } } class ContaPremium { calcularTaxa(valor) { return valor * 0.005; // 0,5% de taxa } }
このモデルを使用すると、戦略パターンを簡単な方法で適用でき、より柔軟でスケーラブルで結合度の低い実装が保証されます。
ストラテジー パターンは、実行コードをさまざまな条件やタイプに直接結合することなく、実行時の操作の動作を変更する必要がある場合の強力なソリューションです。このパターンは、操作の動作がコンテキストに応じて変化する可能性があり、代替手段が互いに独立しているシナリオに最適です。
Strategy を使用することで、システムのより良いメンテナンスと拡張を促進するだけでなく、コードがよりクリーンでモジュール化され、柔軟になることを保証します。
以上が戦略パターンを使用してオーバーコンディショニングを回避するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。