zoukankan      html  css  js  c++  java
  • 设计模式---数据结构模式之职责链模式(Chain of Responsibility)

    一:概念

    职责链模式(CoR,Chain of Responsibility)是行为模式之一,该模式构造一系列分别担当不同的职责的类的对象来共同完成一个任务,这些类的对象之间像链条一样紧密相连,所以被称作职责链模式。
    例1:比如客户Client要完成一个任务,这个任务包括a,b,c,d四个部分。 
    首先客户Client把任务交给A,A完成a部分之后,把任务交给B,B完成b部分,…,直到D完成d部分。 
    例2:比如政府部分的某项工作,县政府先完成自己能处理的部分,不能处理的部分交给省政府,省政府再完成自己职责范围内的部分,不能处理的部分交给中央政府,中央政府最后完成该项工作。 
    例3:软件窗口的消息传播。 
    例4:SERVLET容器的过滤器(Filter)框架实现。

    二:动机

    在软件构建的过程中,一个请求可能被多个对象处理,但是每个请求在运行时只能有一个接受者,如果显示指定,将必不可少的带来请求发送者与接受者的耦合。
    如何使请求的发送者不需要指定具体的接受者?让请求的接受者自己在运行时决定来处理请求,从而使两者解耦。

    三:模式定义

    使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链(链表),并沿着这条链传递请求,直到有一个对象处理它为止。
    
                                                                                               ——《设计模式》GoF

    四:代码讲解

    (一)Request对象:携带请求信息

    class Reqest
    {
        string description;
        RequestType reqType;
    public:
        Reqest(const string & desc, RequestType type) : description(desc), reqType(type) {}
        RequestType getReqType() const { return reqType; }
        const string& getDescription() const { return description; }
    };

    (二)ChainHandler基类处理者:

    class ChainHandler{
        
        ChainHandler *nextChain;  //多态指针指向自己,形成了多态链表

    void sendReqestToNextHandler(const Reqest &
    req)  //若是我的链表的下一个结点不为空,那么久传递给下一个结点进行处理 { if (nextChain != nullptr) nextChain->handle(req); } protected: virtual bool canHandleRequest(const Reqest & req) = 0;  //判断请求能否处理,运行时判断 virtual void processRequest(const Reqest & req) = 0;  //具体处理业务逻辑 public: ChainHandler() { nextChain = nullptr; } void setNextChain(ChainHandler *next) { nextChain = next; }  //建立链表 void handle(const Reqest & req)  //调用方法处理逻辑,当前无法处理,使用下一个 { if (canHandleRequest(req)) processRequest(req); else sendReqestToNextHandler(req); } };

    (三)Handler具体处理对象

    class Handler1 : public ChainHandler{
    protected:
        bool canHandleRequest(const Reqest & req) override
        {
            return req.getReqType() == RequestType::REQ_HANDLER1;
        }
        void processRequest(const Reqest & req) override
        {
            cout << "Handler1 is handle reqest: " << req.getDescription() << endl;
        }
    };
            
    class Handler2 : public ChainHandler{
    protected:
        bool canHandleRequest(const Reqest & req) override
        {
            return req.getReqType() == RequestType::REQ_HANDLER2;
        }
        void processRequest(const Reqest & req) override
        {
            cout << "Handler2 is handle reqest: " << req.getDescription() << endl;
        }
    };
    
    class Handler3 : public ChainHandler{
    protected:
        bool canHandleRequest(const Reqest & req) override
        {
            return req.getReqType() == RequestType::REQ_HANDLER3;
        }
        void processRequest(const Reqest & req) override
        {
            cout << "Handler3 is handle reqest: " << req.getDescription() << endl;
        }
    };

    (四)构建链表

    int main(){
        Handler1 h1;
        Handler2 h2;
        Handler3 h3;
        h1.setNextChain(&h2);  //构建链表
        h2.setNextChain(&h3);
        
        Reqest req("process task ... ", RequestType::REQ_HANDLER3);  //获取请求,设置类型
        h1.handle(req);  //处理请求
        return 0;
    }

    五:类图(结构)

    职责链模式在现在C++中使用不多。但是这种思想还是值得借鉴,比如在python中Django框架数据添加扩展中提到的也是这样的,只要前面不抛出异常,就接着执行

    六:要点总结

    (一)Chain of Responsibility模式的应用场合在于“一个请求可能有多个接受者,但是最后真正接受者只有一个”,这时候请求发送者与接受者的耦合可能出现“变化脆弱”的症状,职责链的目的就是将二者解耦,从而更好的应对变化。

    (二)应用了Chain of Responsibility模式后,对象的职责分派将更具灵活性。我们可以在运行时动态添加/修改请求的处理指责。

    (三)如果请求传递到职责链的末尾仍得不到处理,应该有一个合理的缺省机制。这也是每一个接受者对象的责任,而不是发出请求的对象的责任。

    七:案例实现(代码样例)

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    enum class RequestType
    {
        REQ_HANDLER1,
        REQ_HANDLER2,
        REQ_HANDLER3
    };
    
    class Reqest
    {
        string description;
        RequestType reqType;
    public:
        Reqest(const string & desc, RequestType type) : description(desc), reqType(type) {}
        RequestType getReqType() const { return reqType; }
        const string& getDescription() const { return description; }
    };
    
    class ChainHandler{
    
        ChainHandler *nextChain;
        void sendReqestToNextHandler(const Reqest & req)
        {
            if (nextChain != nullptr)
                nextChain->handle(req);
        }
    protected:
        virtual bool canHandleRequest(const Reqest & req) = 0;
        virtual void processRequest(const Reqest & req) = 0;
    public:
        ChainHandler() { nextChain = nullptr; }
        void setNextChain(ChainHandler *next) { nextChain = next; }
    
    
        void handle(const Reqest & req)
        {
            if (canHandleRequest(req))
                processRequest(req);
            else
                sendReqestToNextHandler(req);
        }
    };
    
    
    class Handler1 : public ChainHandler{
    protected:
        bool canHandleRequest(const Reqest & req) override
        {
            return req.getReqType() == RequestType::REQ_HANDLER1;
        }
        void processRequest(const Reqest & req) override
        {
            cout << "Handler1 is handle reqest: " << req.getDescription() << endl;
        }
    };
    
    class Handler2 : public ChainHandler{
    protected:
        bool canHandleRequest(const Reqest & req) override
        {
            return req.getReqType() == RequestType::REQ_HANDLER2;
        }
        void processRequest(const Reqest & req) override
        {
            cout << "Handler2 is handle reqest: " << req.getDescription() << endl;
        }
    };
    
    class Handler3 : public ChainHandler{
    protected:
        bool canHandleRequest(const Reqest & req) override
        {
            return req.getReqType() == RequestType::REQ_HANDLER3;
        }
        void processRequest(const Reqest & req) override
        {
            cout << "Handler3 is handle reqest: " << req.getDescription() << endl;
        }
    };
    
    int main(){
        Handler1 h1;
        Handler2 h2;
        Handler3 h3;
        h1.setNextChain(&h2);
        h2.setNextChain(&h3);
    
        Reqest req("process task ... ", RequestType::REQ_HANDLER3);
        h1.handle(req);
    
        system("pause");
        return 0;
    }
    全部代码

    八:案例实现(处理汽车)

    (一)handle基类实现

    class CarHandler
    {
    protected:
        CarHandler* nextHandler;
    public:
        virtual void HandlerCar() = 0;
    public:
        CarHandler* SetNextHandler(CarHandler* hand)
        {
            this->nextHandler = hand;
            return this->nextHandler;
        }
    
        virtual ~CarHandler(){}
    };

    (二)实现具体处理子类

    class CarHandleHead :public CarHandler
    {
    public:
        virtual void HandlerCar()
        {
            cout << "composite car head" << endl;
            if (nextHandler != NULL)
                nextHandler->HandlerCar();
        }
    };
    
    class CarHandleBody :public CarHandler
    {
    public:
        virtual void HandlerCar()
        {
            cout << "composite car body" << endl;
            if (nextHandler != NULL)
                nextHandler->HandlerCar();
        }
    };
    
    class CarHandleTail :public CarHandler
    {
    public:
        virtual void HandlerCar()
        {
            cout << "composite car tail" << endl;
            if (nextHandler != NULL)
                nextHandler->HandlerCar();
        }
    };

    (三)组合责任链,开始演示

    void main()
    {
        CarHandler* CH = new CarHandleHead();
        CarHandler* CB = new CarHandleBody();
        CarHandler* CT = new CarHandleTail();
    
        CH->SetNextHandler(CB);
        CB->SetNextHandler(CT);
    
        CH->HandlerCar();
    
        delete CH;
        delete CB;
        delete CT;
    
        system("pause");
        return;
    }

  • 相关阅读:
    辗转相除法求最大公约数和最小公倍数
    KMEANS算法
    Extjs RadioGroup中Radio的切换
    B树、B树、B+树、B*树都是什么
    DBSCAN算法的java实现
    SQL 基础:Select语句,各种join,union用法
    Ubuntu 安装中文输入法 fcitx
    Salesforce 主要发展历史
    Pair Programming(结对编程)
    学习笔记 设计模式之装饰者模式
  • 原文地址:https://www.cnblogs.com/ssyfj/p/9546900.html
Copyright © 2011-2022 走看看