デザインパターンの責任連鎖パターンに関する注意事項
説明する
デザインパターン学習~責任連鎖パターンの書き方を記録。使用される JDK バージョンはバージョン 1.8 です。
責任の連鎖
目的: 複数のオブジェクトにリクエストを処理する機会を与え、それによってリクエストの送信者と受信者の結合を回避します。これらのオブジェクトはチェーンに接続され、リクエストはオブジェクトが処理するまでチェーンに沿って渡されます。
構造:
で:
- ハンドラーはリクエストを処理するためのインターフェースを定義し、(オプション) 後続チェーンを実装します。
- ConcreteHandler は、担当するリクエストを処理します。そのリクエストの後続者にアクセスできます。リクエストが処理できる場合は処理し、そうでない場合はリクエストを後続者に転送します。
- クライアントは、チェーン上の具象ハンドラー (ConcreteHandler) オブジェクトにリクエストを送信します。
適用性:
- リクエストを処理できるオブジェクトは複数あり、どのオブジェクトがリクエストを処理するかは実行時に自動的に決定されます。
- 受信者を明示的に指定せずに、複数のオブジェクトの 1 つにリクエストを送信したい。
- リクエストを処理できるオブジェクトのセットは動的に指定する必要があります。
目次
責任連鎖パターンのクラス図の例
この UML クラス図を使用して、責任連鎖パターンの例を実装します。
休暇リクエストのタイプ
package com.example.deesign_patterns.responsibility;
//请假条类
public class LeaveRequest {
//姓名
private String name;
//请假天数
private int num;
//请假内容
private String content;
public LeaveRequest(String name, int num, String content) {
this.name = name;
this.num = num;
this.content = content;
}
public String getName() {
return name;
}
public int getNum() {
return num;
}
public String getContent() {
return content;
}
}
抽象ハンドラクラス
package com.example.deesign_patterns.responsibility;
//抽象处理者类
public abstract class Handler {
protected final static int NUM_ONE=1;
protected final static int NUM_THREE=3;
protected final static int NUM_SEVEN=7;
//该领导处理的请求天数区间
private int numStart;
private int numEnd;
//声明后续者(声明上级领导)
private Handler nextHandler;
public Handler(int numStart){
this.numStart=numStart;
}
public Handler(int numStart,int numEnd){
this.numStart=numStart;
this.numEnd=numEnd;
}
//设置上级领导对象
public void setNextHandler(Handler nextHandler) {
this.nextHandler = nextHandler;
}
//各级领导处理请假条的方法
protected abstract void handleLeave(LeaveRequest leave);
//提交请求条
public final void submit(LeaveRequest leave){
//该领导进行审批
this.handleLeave(leave);
//判断是否有上级领导且该领导能否处理
if(this.nextHandler!=null&&leave.getNum()>this.numEnd){
//提交给上级领导进行审批
this.nextHandler.submit(leave);
}else {
System.out.println("流程结束!");
}
}
}
グループリーダー部門
package com.example.deesign_patterns.responsibility;
//小组长类(具体的处理者)
public class GroupLeader extends Handler{
//定义小组长批准天数为1天
public GroupLeader() {
super(0,Handler.NUM_ONE);
}
@Override
protected void handleLeave(LeaveRequest leave) {
System.out.println(leave.getName()+"请假"+leave.getNum()+"天,"+leave.getContent()+"。");
System.out.println("小组长审批:同意");
}
}
部長クラス
package com.example.deesign_patterns.responsibility;
//部门经理类(具体的处理者)
public class Manager extends Handler{
//部门经理批准天数为1-3天
public Manager() {
super(Handler.NUM_ONE,Handler.NUM_THREE);
}
@Override
protected void handleLeave(LeaveRequest leave) {
System.out.println(leave.getName()+"请假"+leave.getNum()+"天,"+leave.getContent()+"。");
System.out.println("部门经理审批:同意");
}
}
ゼネラルマネージャー
package com.example.deesign_patterns.responsibility;
//总经理类(具体的处理者)
public class GeneralManager extends Handler{
//总经理批准天数为3-7天
public GeneralManager() {
super(Handler.NUM_THREE,Handler.NUM_SEVEN);
}
@Override
protected void handleLeave(LeaveRequest leave) {
System.out.println(leave.getName()+"请假"+leave.getNum()+"天,"+leave.getContent()+"。");
System.out.println("总经理审批:同意");
}
}
テストクラス
package com.example.deesign_patterns.responsibility;
//测试类
public class Client {
public static void main(String[] args) {
//创建一个请假条对象
LeaveRequest leave=new LeaveRequest("小明",7,"身体不适");
//创建各级领导对象
GroupLeader groupLeader=new GroupLeader();
Manager manager=new Manager();
GeneralManager generalManager=new GeneralManager();
//设置处理者链
groupLeader.setNextHandler(manager);
manager.setNextHandler(generalManager);
//小明提交请假申请
groupLeader.submit(leave);
}
}
利点:
- オブジェクト間の結合を減らします。このパターンにより、リクエストの送信者と受信者の間の結合が軽減されます。
- システムの拡張性が強化されました。開始および終了の原則を満たすために、必要に応じて新しい要求処理クラスを追加できます。
- オブジェクトに責任を割り当てる際の柔軟性が向上しました。ワークフローが変更されると、チェーン内のメンバーを動的に変更したり、その順序を変更したりできます。また、責任を動的に追加または削除することもできます。
- 責任の連鎖により、オブジェクト間の接続が簡素化されます。オブジェクトは後続オブジェクトへの参照を維持するだけでよく、他のすべてのハンドラーへの参照を維持する必要がないため、多数の if または if...else ステートメントの使用が回避されます。
- 責任の共有。各クラスは、処理すべき作業のみを処理する必要があり、処理されなかった作業は次のオブジェクトに渡されて完了します。これにより、各タイプの責任の範囲が明確に定義され、クラスの単一責任の原則に準拠します。
欠点:
- すべてのリクエストが処理されるという保証はありません。リクエストには明確な受信者がないため、リクエストが処理されるという保証はなく、チェーンの最後に到達するまでリクエストは処理されない可能性があります。
- より長い責任の連鎖と比較して、リクエストの処理には複数の処理オブジェクトが関与する可能性があり、システムのパフォーマンスはある程度の影響を受けます。
- 責任連鎖確立の合理性はクライアント側で保証する必要があるため、クライアントの複雑性が増し、循環呼び出しなど責任連鎖の設定ミスによりシステムエラーが発生する可能性があります。