zoukankan      html  css  js  c++  java
  • 【设计模式】责任链模式

    1、定义

    1.1 标准定义

      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.(使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。) 

    1.2 通用类图

      责任链模式的核心在上, 是由多个处理者ConcreteHandler组成的。

    2、实现

    2.1 类图

      抽象处理者(Handler)角色:定义出一个处理请求的接口。如果需要,接口可以定义出一个方法,以设定和返回对下家的引用。这个角色通常由一个抽象类或接口实现。

      具体处理者(ConcreteHandler)角色:具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家。

    2.2 代码

    2.2.1 Hander类

    // Chander.h
    
    #include <iostream>
    
    class CResponse;
    class CRequest;
    
    class CHander
    {
    public:
        CHander();
        ~CHander();
    
        CResponse  * mopHandleMessage(CRequest  *opRequest);
    
        void mvSetNext(CHander  *opHander);
    
    protected:
        virtual std::string msGetEcho() = 0;
    
    protected:
        CHander *mopNexthander;
        int          miLevel;
    };
    
    //  构造三个链成员
    class CHander_1 : public CHander
    {
    public:
        CHander_1();
        ~CHander_1();
        
        virtual std::string msGetEcho();
    };
    
    class CHander_2 : public CHander
    {
    public:
        CHander_2();
        ~CHander_2();
    
        virtual std::string msGetEcho();
    };
    
    class CHander_3 : public CHander
    {
    public:
        CHander_3();
        ~CHander_3();
    
        virtual std::string msGetEcho();
    };
    
    // 请求  
    class CRequest
    {
    public:
        int miNumber;
    };
    
    // 反馈
    class CResponse
    {
    public:
        CResponse(const std::string &sResponse);
        ~CResponse();
    
        // 获取请求处理结果
        std::string msGetResponse();
    
    private:
        std::string msResponse;
    };
    // Chander.cpp
    
    #include "CHander.h"
    
    // CHander
    CHander::CHander() {};
    
    CHander::~CHander(){};
    
    CResponse  *CHander::mopHandleMessage(CRequest *opRequest)
    {
        if (miLevel == opRequest->miNumber)
        {
            return new CResponse(msGetEcho());
        }
        else
        {
            if (NULL != mopNexthander)
            {
                return mopNexthander->mopHandleMessage(opRequest);
            }
        }
    
        return new CResponse("No Handle.");
    }
    
    void CHander::mvSetNext(CHander  *opHander)
    {
        this->mopNexthander = opHander;
    }
    
    // CHander_1
    CHander_1::CHander_1()
    {
        // 定义级别
        miLevel = 1;
        mopNexthander = NULL;
    }
    
    CHander_1::~CHander_1(){};
    
    std::string CHander_1::msGetEcho()
    {
        return "CHander_1 message.
    ";
    }
    
    // CHander_2
    CHander_2::CHander_2()
    {
        // 定义级别
        miLevel = 2;
        mopNexthander = NULL;
    }
    
    CHander_2::~CHander_2(){};
    
    std::string CHander_2::msGetEcho()
    {
        return "CHander_2 message.
    ";
    }
    
    // CHander_3
    CHander_3::CHander_3()
    {
        // 定义级别
        miLevel = 3;
        mopNexthander = NULL;
    }
    
    CHander_3::~CHander_3(){};
    
    std::string CHander_3::msGetEcho()
    {
        return "CHander_3 message.
    ";
    }
    
    //CResponse
    CResponse::CResponse(const std::string &sResponse) : msResponse(sResponse){}
    
    CResponse::~CResponse(){};
    
    std::string CResponse::msGetResponse()
    {
        return msResponse;
    }

    2.2.3 调用

    #include <iostream>
    #include "CHander.h"
    
    using namespace std;
    
    int main()
    {
        CHander *opHander1 = new CHander_1;
        CHander *opHander2 = new CHander_2;
        CHander *opHander3 = new CHander_3;
        
        //构造执行链
        opHander1->mvSetNext(opHander2);
        opHander2->mvSetNext(opHander3);
    
        CRequest *opRequest = new CRequest;
        opRequest->miNumber = 2;
        CResponse *opResponse = opHander1->mopHandleMessage(opRequest);
        std::cout << opResponse->msGetResponse().c_str() << endl;
        delete opResponse;
        opResponse = NULL;
    
        opRequest->miNumber = 1;
        opResponse = opHander1->mopHandleMessage(opRequest);
        std::cout << opResponse->msGetResponse().c_str() << endl;
        delete opResponse;
        opResponse = NULL;
    
        opRequest->miNumber = 4;
        opResponse = opHander1->mopHandleMessage(opRequest);
        std::cout << opResponse->msGetResponse().c_str() << endl;
        delete opResponse;
        opResponse = NULL;
    
        delete opHander1;
        delete opHander2;
        delete opHander3;
    
        return 0;
    }

    2.2.3 执行结果

    3、优缺点

    3.1 优点

      责任链模式非常显著的优点是将请求和处理分开。请求者可以不用知道是谁处理的,处理者可以不用知道请求的全貌。两者解耦,提高系统的灵活性。

    3.2 缺点

      责任链有两个非常显著的缺点:一是性能问题,每个请求都是从链头遍历到链尾,特别是在链比较长的时候,性能是一个非常大的问题。二是调试不很方便,特别是链条比较长,环节比较多的时候,由于采用了类似递归的方式,调试的时候逻辑可能比较复杂。

     3.3 注意

      链中节点数量需要控制,避免出现超长链的情况,一般的做法是在Handler中设置一个最大节点数量,在setNext方法中判断是否已经是超过其阈值,超过则不允许该链建立,避免无意识地破坏系统性能。

    3.4 总结

      在例子和通用源码中CHandler是抽象类, 融合了模板方法模式, 每个实现类只要实现 echo方法处理请求和设置自身级别, 想想单一职责原则和迪米特法则吧, 通过融合模板方法模式, 各个实现类只要关注的自己业务逻辑就成了, 至于说什么事要自己处理, 那就让父类去决定好了, 也就是说父类实现了请求传递的功能, 子类实现请求的处理, 符合单一职责原则, 各个实现类只完成一个动作或逻辑,也就是只有一个原因引起类的改变,在使用的时候用这种方法, 好处是非常明显的了,子类的实现非常简单,责任链的建立也是非常灵活的。责任链模式屏蔽了请求的处理过程,你发起一个请求到底是谁处理的,这个你不用关心,只要你把请求抛给责任链的第一个处理者, 最终会返回一个处理结果( 当然也可以不做任何处理), 为请求者可以不用知道到底是需要谁来处理的,这是责任链模式的核心,同时责任链模式也可以作为一种补救模式来使用。举个简单例子,如项目开发的时候, 需求确认是这样的:一个请求(如银行客户存款的币种),一个处理者( 只处理人民币),但是随着业务的发展(改革开放了嘛,还要处理美元、日元等),处理者的数量和类型都有所增, 那这时候就可以在第一个处理者后面建立一个链,也就是责任链来处理请求,如果是人民币,好,还是第一个业务逻辑来处理;如果是美元,好,传递到第二个业务逻辑来处理;日元、 欧元……这些都不用在对原有的业务逻辑产生很大改变, 通过扩展实现类就可以很好的解决这些需求的变更问题。

  • 相关阅读:
    ASP.NET 表单验证 Part.2(实现表单验证)
    长工的买房故事
    软件界面交互和易用性改进总结[zz]
    访问hotmail邮箱的途径
    Google内部收集员工创意的方法[转载]
    Web2.0地图展望
    C++开源跨平台类库集
    庆祝lucky荣登早教网首页宝宝
    在那些打磨汉芯的日子里[转贴]
    在中国搞技术只能混碗饭吃,没有太大希望
  • 原文地址:https://www.cnblogs.com/ChinaHook/p/7248075.html
Copyright © 2011-2022 走看看