行为型设计模式------职责链模式

什么是行为型设计模式

行为型设计模式是对在不同的对象之间的责任划分和算法的抽象化。它不仅关注类和对象的结构,而且重点关注他们之间的相互作用。

通过行为型设计模式,可以更加清晰的划分类和对象的职责,并研究系统在运行时不同实例对象之间的交互。在系统运行的过程中,对象的存在并不是孤立的,它可以通过相互通信和协作来完成某些复杂的功能,一个对象的运行也会影响到其他的对象。

行为型设计模式可以分为类行为型和对象行为型。

  • 类行为型,通过类的继承关系来在类之间分配行为,主要利用了多态的方式来实现
  • 对象行为型,主要通过对象之间的关联关系来实现行为的分配,根据“合成复用原则”,一个系统中尽量使用关联关系来代替继承关系,所以常见的行为型就是对象行为型设计模式。

职责链模式

引子

在斗地主游戏中,上家出一张牌以后,下家查看手牌,如果要不起则将出牌的请求传递给他的下家,下家再次判断。如果一个循环结束,其他人都要不起这张牌,那么上家可以继续出牌。在这个过程中,出牌的请求沿着一条链传递,链上的每一位玩家都可以处理这个请求或者放弃这个请求继续传递。
斗地主的出牌请求传递

模式动机

很多情况下,一个系统中处理某个请求的对象不止一个,那么我们可以构建一个链式结构,让请求沿着这条链进行传播,这条链就成为职责链

职责链可以有很多形式,直线、环、树形,但是常见的就是直线型的链来传递请求。

描述:链上的每一个对象都是请求的处理者,职责链将可以处理请求的处理者组织成一条链,让请求在链上传播,由链上的处理者处理这个请求。客户端只要将请求发送到链上即可,不需要关系具体的处理细节和请求的传递,实现了请求发送者和请求处理者的解耦。

模式结构和说明

职责链模式结构图

  • Handler抽象处理者角色,定义了一个处理请求的抽象方法,由具体处理者角色去实现这个方法。因为每一个处理者的下家还是一个处理者,所以定义了一个抽象处理者对象的引用来作为其对下家的引用。通过这个引用可以让处理者形成一条链。
  • ConcereHandler具体处理者对象,实现请求处理方法。在处理请求前判断是否有权限来处理请求,如果有则处理,如果没有则将请求传递给下一个处理者。通过下一个处理者的引用来转发请求。

设计

核心的类就是抽象处理者类的设计:

public abstract class Handler {
	//protected 子类可访问
    protected Handler successor;
    public void setSuccessor(Handler successor) {
        this.successor = successor;
    }
    public abstract void handleRequest(String request);
}

具体抽象者类的设计:

public class ConcreteHandler extends Handler{
    @Override
    public void handleRequest(String request) {
        if (请求是否满足条件) {
            //处理请求
        } else {
            this.successor.handleRequest(request);//转发请求
        }
    }
}

示例

场景:员工请假的时候,如果天数day < 3,主任可审批;3<=day<10经理可以审批;day > 10提示拒绝请求。
首先是请假条:

package design_model.dutyline;

public class LeaveRequest {
    private String name;
    private int day;
    public LeaveRequest(String reason, int day) {
        this.name = reason;
        this.day = day;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getDay() {
        return day;
    }
    public void setDay(int day) {
        this.day = day;
    }
}

抽象处理者类:

public abstract class Leader {
    protected String name;
    protected Leader successor;

    public Leader(String name) {
        this.name = name;
    }

    public void setSuccessor(Leader successor) {
        this.successor = successor;
    }
    public abstract void handleRequest(LeaveRequest request);
}

具体的处理者类:


public class Director extends Leader {
    public Director(String name) {
        super(name);
    }
    @Override
    public void handleRequest(LeaveRequest request) {
        if (request.getDay() < 3) {
            System.out.println("主任" + name + "审批员工" + request.getName() + "的请假条,请假天数为" + request.getDay() + "天。");
        } else {
            if (this.successor != null) {
                this.successor.handleRequest(request);
            }
        }
    }
}
public class Manager extends Leader {
    public Manager(String name) {
        super(name);
    }

    @Override
    public void handleRequest(LeaveRequest request) {
        if (request.getDay() >= 3 && request.getDay() < 10) {
            System.out.println("经理" + name + "审批员工" + request.getName() + "的请假条,请假天数为" + request.getDay() + "天。");
        } else {
            System.out.println("员工" + request.getName() + "竟然想请假  " + request.getDay() + "  天,不可能的!");
        }
    }
}

客户端类:

public class Client {

    public static void main(String[] args) {
        Leader director,manager;
        director = new Director("王某某");
        manager = new Manager("李三");
        director.setSuccessor(manager);

        LeaveRequest lr = new LeaveRequest("老王", 2);
        director.handleRequest(lr);

        LeaveRequest lr2 = new LeaveRequest("老李", 5);
        director.handleRequest(lr2);

        LeaveRequest lr3 = new LeaveRequest("老张", 20);
        director.handleRequest(lr3);

    }
}
//输出结果:
主任王某某审批员工老王的请假条,请假天数为2天。
经理李三审批员工老李的请假条,请假天数为5天。
员工老张竟然想请假  20  天,不可能的!

注:客户端负责职责链的创建

优缺点

优点:

  • 接收方和发送方都不需要明确对方的状态,只需要知道一个请求最终会被处理即可
  • 一个处理者对象只需要维护它的后继处理者对象的引用即可
  • 可以动态的增加或修改处理者的请求处理方式
  • 需要动态增加一个处理者时仅修改客户端代码即可

缺点:

  • 如果没有一个明确的处理者,一个请求不一定能得到处理
  • 如果职责链过长的话,系统性能会收到一定影响,而且调试比较复杂
  • 如果建立职责链不当的话,可能会造成死循环

适用场景

  • 一个请求有多个对象可以处理,具体哪个对象进行处理可以在运行时确定,客户端只需要把它提交到链上,而不需要关系是哪个对象处理了这个请求
  • 在不确定指定接收者的情况下,将请求提交给多个请求处理者中的一个
  • 可以动态的指定一组对象处理这个请求,还可以调整请求处理的次序

常见的使用场景:

  1. java的异常处理
        try {

        } catch (ArrayIndexOutOfBoundsException e) {

        } catch (ArithmeticException e) {

        } catch (Exception e) {
            
        }

模式扩展

  • 纯的职责链模式:即每个请求要么被全部处理,要么将请求传递给下一个处理者。
  • 不纯的职责链模式:每一个请求处理者可以处理部分请求,然后将剩下的传递给下一个处理者

猜你喜欢

转载自blog.csdn.net/machine_Heaven/article/details/105145042
今日推荐