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

  • 相关阅读:
    Truck History(poj 1789)
    Highways poj 2485
    117. Populating Next Right Pointers in Each Node II
    116. Populating Next Right Pointers in Each Node
    115. Distinct Subsequences
    114. Flatten Binary Tree to Linked List
    113. Path Sum II
    109. Convert Sorted List to Binary Search Tree
    106. Construct Binary Tree from Inorder and Postorder Traversal
    105. Construct Binary Tree from Preorder and Inorder Traversal
  • 原文地址:https://www.cnblogs.com/ChinaHook/p/7248075.html
Copyright © 2011-2022 走看看