责任链模式

begin 2021年12月11日20:47:41

责任链模式

定义

Avoid coupling the sender of a request to its receiver by giving more than one
object a chance to handle the request. Chain the receiving objects and pass the
request along the chain until an object handles it. ——《Design Patterns: Elements of Reusable Object-Oriented Software》

使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将接收对象连城一条链,并沿着链传递该请求,直到有一个对象处理它为止。 ——《设计模式:可复用面向对象软件的基础》

责任链模式是一种行为型设计模式。

使用场景

在以下场景下使用责任链模式:

  • 有多个对象处理一个请求时,且处理者不知道处理优先级。
  • 你想让多个处理者处理一个请求,不需要知道具体处理者。
  • 处理请求的对象集合应该是自动确定的。

总的来说,就是处理请求的处理者有多个,但是客户端只知道其中一个,其他都是主动排好队,等着处理请求的。

图示

责任链结构图:

责任链结构图

角色

客户端(Client):

  • 初始化请求给责任链上的一个具体处理者

抽象处理者(Handler):

  • 定义一个处理请求的接口
  • 设置下一位处理者的引用

具体处理者(ConcreteHandler1、ConcreteHandler2):

  • 处理它负责的请求
  • 如果具体处理者可以处理请求,就处理;否则,将请求交给它的继承者

请求(Request):

  • 封装了需要处理的信息,传递给处理者进行处理。

代码示例

// 抽象处理者类
abstract class Handler {
    protected Handler successor;

    public void setSuccessor(Handler successor) {
        this.successor = successor;
    }

    public abstract void handleRequest(Request request);
}

// 具体处理者类A
class HandlerA extends Handler {
    public void handleRequest(Request request) {
        if (request.getType() == RequestType.TYPE_A) {
            // 处理请求
        } else if (successor != null) {
            successor.handleRequest(request);
        }
    }
}

// 具体处理者类B
class HandlerB extends Handler {
    public void handleRequest(Request request) {
        if (request.getType() == RequestType.TYPE_B) {
            // 处理请求
        } else if (successor != null) {
            successor.handleRequest(request);
        }
    }
}

// 请求类
class Request {
    private RequestType type;

    public Request(RequestType type) {
        this.type = type;
    }

    public RequestType getType() {
        return type;
    }
}

// 请求类型枚举类
enum RequestType {
    TYPE_A, TYPE_B
}

// 使用示例
public class Client {
    public static void main(String[] args) {
        Handler handlerA = new HandlerA();
        Handler handlerB = new HandlerB();
        handlerA.setSuccessor(handlerB);

        Request request1 = new Request(RequestType.TYPE_A);
        handlerA.handleRequest(request1);

        Request request2 = new Request(RequestType.TYPE_B);
        handlerA.handleRequest(request2);
    }
}

故事版代码示例

产房内哇的一声啼哭,你已经降临这个世界。

你慢慢长大,学习,工作,结婚生子。

爸妈永远是你的支持。

public interface Support {
    void setSuccessor(Support successor);
    void handle(You you);
}

public class MaMa implements Support {
    private String name = "妈妈";
    private Support successor;
    @Override
    public void setSuccessor(Support successor) {
        this.successor = successor;
    }

    @Override
    public void handle(You you) {
        if (you.getObtainType() == ObtainType.NAME) {
            System.out.println(name + ":怀孕了,起个好听的名字");
            successor.handle(you);
        } else if (you.getObtainType() == ObtainType.BORN) {
            System.out.println(name + ":十月怀胎,你出生了");
            successor.handle(you);
        } else if (you.getObtainType() == ObtainType.EDUCATION) {
            System.out.println(name + ":十六年努力工作,提供给你最好的教育");
            successor.handle(you);
        } else if (you.getObtainType() == ObtainType.WORK) {
            System.out.println(name + ":给你鼓励");
            successor.handle(you);
        } else if (you.getObtainType() == ObtainType.MARRIAGE) {
            System.out.println(name + ":倾尽所有买房买车");
            successor.handle(you);
        }
    }
}

public class BaBa implements Support{
    private String name = "爸爸";
    private Support successor;
    @Override
    public void setSuccessor(Support successor) {
        this.successor = successor;
    }

    @Override
    public void handle(You you) {
        if (you.getObtainType() == ObtainType.NAME) {
            System.out.println(name + ":让岳父起个好听的名字");
            successor.handle(you);
        } else if (you.getObtainType() == ObtainType.BORN) {
            System.out.println(name + ":高兴");
            successor.handle(you);
        } else if (you.getObtainType() == ObtainType.EDUCATION) {
            System.out.println(name + ":十六年和妈妈一起努力工作,提供给你最好的教育");
            successor.handle(you);
        } else if (you.getObtainType() == ObtainType.WORK) {
            System.out.println(name + ":给你指导");
            successor.handle(you);
        } else if (you.getObtainType() == ObtainType.MARRIAGE) {
            System.out.println(name + ":和妈妈一起倾尽所有买房买车");
            successor.handle(you);
        }
    }
}

public class WaiGong implements Support {
    private String name = "外公";
    private Support successor;
    @Override
    public void setSuccessor(Support successor) {
        this.successor = successor;
    }

    @Override
    public void handle(You you) {
        if (you.getObtainType() == ObtainType.NAME) {
            System.out.println(name + ":名叫晓月");
        } else if (you.getObtainType() == ObtainType.BORN) {
            System.out.println(name + ":你们多了一份责任");
        } else if (you.getObtainType() == ObtainType.EDUCATION) {
            System.out.println(name + ":暑假的大热天的扇子,冬天热乎的番薯");
        } else if (you.getObtainType() == ObtainType.WORK) {
            System.out.println(name + ":你很努力,也很棒");
        } else if (you.getObtainType() == ObtainType.MARRIAGE) {
            System.out.println(name + ":开心看到你结婚");
        }
    }
}

public class Family {
    public static void main(String[] args) {
        // 爸爸
        BaBa baBa = new BaBa();
        // 妈妈
        MaMa maMa = new MaMa();
        // 外公
        WaiGong waiGong = new WaiGong();

        // 结婚,爸爸成了妈妈的支持
        maMa.setSuccessor(baBa);
        // 外公对爸爸说,我们是一家人,我可以成为你的支持
        baBa.setSuccessor(waiGong);
        // 妈妈怀孕了
        You you = new You();
        you.setAge(-1);
        // 你一生的支持,103岁die
        while(you.getAge() < 103) {
            // 你主观或者客观提出了请求
            produceRequest(you);
            // 家人支持处理你的请求
            handleRequest(you, maMa);
            // 下一重要阶段
            setNextAge(you);
        }

    }

    private static void setNextAge(You you) {
        if (you.getAge() == -1) {
            you.setAge(0);
        } else if (you.getAge() == 0) {
            you.setAge(3);
        } else if (you.getAge() >= 3 && you.getAge() < 22) {
            you.setAge(22);
        } else if (you.getAge() >= 22 && you.getAge() < 24) {
            you.setAge(24);
        } else if (you.getAge() == 24) {
            you.setAge(103);
        }
    }

    private static void handleRequest(You you, MaMa maMa) {
        maMa.handle(you);
    }

    private static void produceRequest(You you) {
        if (you.getAge() == -1) {
            you.setObtainType(ObtainType.NAME);
        } else if (you.getAge() == 0) {
            you.setObtainType(ObtainType.BORN);
        } else if (you.getAge() >= 3 && you.getAge() < 22) {
            you.setObtainType(ObtainType.EDUCATION);
        } else if (you.getAge() >= 22 && you.getAge() < 24) {
            you.setObtainType(ObtainType.WORK);
        } else if (you.getAge() == 24) {
            you.setObtainType(ObtainType.MARRIAGE);
        }
    }
}

代码示例结果:

责任链模式示例结果图

优点

责任链模式的优点在于它可以将请求的处理分散到多个对象中,降低了对象之间的耦合度。同时,责任链模式也比较灵活,可以动态地组织处理者链,以满足不同的需求。

缺点

但是责任链模式也有一些缺点。首先,由于每个处理者都要处理请求,因此处理者链过长或者处理者数量过多可能会影响性能。其次,如果处理者链没有被正确组织,可能会导致请求无法得到处理或者处理不当的情况发生。

总结

当你需要多个处理者处理一个请求,并想任意组合处理者时,可以使用责任链模式。该模式具有降低耦合,以及灵活组织处理者的优点。

2023年03月19日17:36:53

posted on 2023-03-19 17:38  mingmingcome  阅读(124)  评论(0编辑  收藏  举报

导航