はじめに
今日はChainOfResponsibility パターンについて実装します。
一言で表すと、「たらいまわし」ですかね。
設計と実装
今回は、日報と週報をどこからか取得してくる際に、このChainOfResponsibilityパターンを使って実装します。
GetReportDataHandlerに、「このレポート出して!」とお願いします。受け取った側は、自身がその担当ではなければ「担当の者にお繋します」といった具合に、たらいまわしにしていきます。
設計は以下です。
次に上記を元に実装をしてみます。
// 日報
public class DailyWorkHoursReportHandler : IGetReportDataHandler
{
public IGetReportDataHandler Next { get; set; }
public void Request(ReportType reportType)
{
if (reportType == ReportType.Daily)
{
Console.WriteLine("日報のデータを取得します。");
}
else if (Next != null)
{
Next.Request(reportType);
}
else
{
Console.WriteLine("対応するレポートタイプではありません");
}
}
}
internal class Program
{
static void Main(string[] args)
{
// レポートタイプを指定してデータを取得
IGetReportDataHandler handler = new MonthlyWorkHoursReportHandler();
handler.Next = new DailyWorkHoursReportHandler();
handler.Request(ReportType.Monthly);
handler.Request(ReportType.Daily);
handler.Request(ReportType.Weekly);
Console.ReadKey();
}
}
このような形で型が日報ではない場合は、Nextで指定した週報に処理を委譲します。
メリット・デメリット
以下にChatGPTの考えるメリットデメリットを記します。
Chain of Responsibility(責任の連鎖)は、ソフトウェアデザインパターンの一つであり、複数のオブジェクトが順番に処理を試み、処理できるオブジェクトが見つかるまで処理を続けることが特徴です。以下に、Chain of Responsibility パターンのメリットとデメリットをいくつか挙げてみましょう。
メリット:
柔軟性と拡張性:
イベントや要求の処理を順番に行うことで、各オブジェクトが責任を持つ範囲が明確になります。これにより、新しい処理を追加したり既存の処理を変更する際に、既存のコードを変更せずに追加できるため、柔軟性と拡張性が向上します。
単一責任の原則:
各処理オブジェクトは自身の責務に焦点を当て、他のオブジェクトとの結合を最小限に抑えます。これにより、単一責任の原則を守ることができます。
再利用性:
各処理オブジェクトは独立して再利用可能であるため、他のコンテキストやシナリオで同じ処理を再利用することが容易です。
デメリット:
パフォーマンスの低下:
チェーン内の全てのオブジェクトが順番に処理を試みるため、処理が終了するまでにすべてのオブジェクトを通過する必要があります。これが無駄な場合や、処理が複雑な場合にはパフォーマンスの低下が考えられます。
デバッグが難しい:
どのオブジェクトが処理を行ったかを特定することが難しい場合があります。特に大規模で複雑なチェーンがある場合、デバッグが複雑になる可能性があります。
全体の流れが分散する:
責任が複数のオブジェクトに分散されるため、処理の全体の流れが明確でなくなることがあります。これが理解しにくいコードやバグの原因となる可能性があります。
Chain of Responsibility パターンは、特定の状況や要件に対して適している場合がありますが、全てのシナリオに適しているわけではありません。利用する際には、コードの保守性や可読性、パフォーマンスの要件などを考慮する必要があります。
終わりに
今回はChainOfResponsibility パターンについて学習しました。多用するパターンではないかもというのが正直な感想ですね。全パターン網羅まで引き続き学習をしていきたいと思います。