zoukankan      html  css  js  c++  java
  • 设计模式 笔记 责任链模式 chain of responsibility


    //---------------------------15/04/25----------------------------


    //Chain of responsibility 责任链-----对象行为型模式

    /*

        1:意图:

            使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这些对象

            连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

        2:动机:

        3:适用性:

            1>有多个对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定。

            2>你想在不明确指定接受者的情况下,向多个对象中的一个 请求提交一个请求。

            3>可处理一个请求的对象集合应被动态指定。

        4:结构:

     

            Client-------------->Handler:<---------

                                 successor---------|

                                 HandleRequest(){ successor->HandleRequest()}

                                    |

                            -------------------

                            |                 |

                        ConcreteHandler1:  ConcereteHandler2:

                        HandleRequest()    HandleRequest()

                        { if can handle

                          { do something}

                          else

                          { Handler::HandleRequest()}

                        }

        5:参与者:

            1>Handler

                1)定义一个处理请求的接口。

                2)(可选)实现后继链。

            2>ConcreteHandler

                1)处理它所负责的请求。

                2)可访问它的后继者。

                3)如果可处理该请求,就处理之;否则将该请求转发给它的后继者。

            3>Clinet

                向链上的具体处理者对象提交请求。

        6:协作:

            当客户提交一个请求时,请求沿着链传递直至有一个ConcreteHandler对象负责处理它。

        7:效果:

          优点:

            1>降低耦合度:

                该模式使得对象无需知道是其他哪一个对象处理其请求。接收者和发送者都没有对方的明确的

                信息,且链中的对象不需知道链的结构。

                所以责任链可简化对象的相互连接。

            2>增强了给对象指派职责的灵活性:

                可以在运行时刻动态增加或修改职责。

          缺点:

            1>不保证被接受。

                既然一个请求没有明确的就收者,那么不能保证一定会被处理。

            2>当链条太长时,会有效率问题(ps:这一点是我自己加的)

                和明确指派任务相比,这么做或多或少会损失点效率,所以不能乱用。

        8:实现:

            1>实现后继者链:

                1)定义新的链接:

                    没有已有链接时只能自己定义了。

                2)使用已有的链接:

                    如果已经有个链接了,比如说Composite模式中定义了Parent的引用。直接拿来用就行了

                    也就是把父部件当作后继者,因为责任链一般都是向传递的,也就是越往越普通。

     

            2>链接后继者:

                如果是自己定义一个后继者链,Handler不仅要定义接口,通常也要维护链接。也就是要提供一个

                缺省实现:向后继者转发请求。

            3>表示请求:

                1)硬编码:

                    也就是直接调用,这样只能表示一种请求类型。

                2)使用处理函数:

                    通过传递参数来判断请求的类型。这就需要发送者和接收者在编码问题上达成一致。

        9:代码示例:                                                                     */

    //定义了请求的类型

    typedef int Topic;

    const Topic NO_HELP_TOPIC = -1;


    //Handler 定义了各种接口

    class HelpHandler

    {

    public:

        HelpHandler(HelpHandler* = 0, Topic = NO_HELP_TOPIC);

        virtual bool HasHelp();

        virtual void SetHandler(HelpHandler*, Topic);

        virtual void HandleHelp();

        

    private:

        HelpHandler* _successor;

        Topic _topic;

    };


    HelpHandler::HelpHandler(HelpHandler* h, Topic t)

        : _successor(h), _topic(t)  {}


    bool HelpHandler::hasHelp()

    {

        return _topic != NO_HELP_TOPIC;

    }


    //调用后继者的HandleHelp()

    void HelpHandler::HandleHelp()

    {

        if(_successor != 0)

            _successor->HandleHelp();

    }


    //ConcreteHandler中的abstract 听起来很奇怪,但是就是这样的

    //很多东西都有帮助,窗口组件则一般都会有帮助,所以定义一个继承子Handlerabstract

    //但是它确实也属于HandlerConcreteHandler类,因为它指定了是窗口组件类。

    class Widget : public HelpHandler

    {

    protected:

        Widget(Widget* parent, Topic t = NO_HELP_TOPIC);

        

    private:

        Widget* _parent;

    };


    Widget::Widget(Widget* w, Topic t) : HelpHandler(w, t)

    {

        _parent = w;

    }


    //ConcreteHandler 具体的处理者。

    class Button : public Widget

    {

    public:

        Button(Widget* d, Topic t = NO_HELP_TOPIC);

        virtual void HandleHelp();

    };


    Button::Button(Widget* h, Topic t) : Widget(h, t){}


    //如果有帮助就调用,否则传递给后继者(如果有的话)

    void Button::HandleHelp()

    {

        if(HasHelp())

        {

            

            //do something

        }

        else

        {

            HelpHandler::HandleHelp();

        }

    }


    //ConcreteHandler:类似上面,只不过它后继者可以是任意的帮助类,而不一定只是窗口类

    class Dialog : public Widget

    {

    public:

        Dialog(HelpHandler* h, Topic = NO_HELP_TOPIC);

        virtual void HandleHelp();

    };


    Dialog::Dialog(HelpHandler* h, Topic t) : Widget(0)

    {

        SetHandler(h, t);

    }


    void Dialog::HandleHelp()

    {

        if(HasHelp())

        {

            //do something

        }

        else

        {

            HelpHandler::HandleHelp();

        }

    }


    //ConcreteHandler:最后一个节点,没有后继者了。

    class Application : public HelpHandler

    {

        Application(Topic t) : HelpHandler(0, t){}

        virtual void HandleHelp();

    };


    void Application::HandleHelp()

    {

        //do something

    }



    const Topic PRINT_TOPIC = 1;

    const Topic PAPER_ORIENTATION_TOPIC = 2;

    const Topic APPLICATION_TOPIC = 3;


    Application* application = new Application(APPLICATION_TOPIC);

    Dialog* dialog = new Dialog(application, PRINT_TOPIC);

    Button* button = new Button(dialog, PAPER_ORIENTATION_TOPIC);


    //这里Button有自己的帮助(PAPER_ORIENTATION_TOPIC)所以会自己处理,并不会交给后继者

    //当然如果里面的do something中调用了Handler::HandlerHelp(),那么还是会传递下去的。

    button->HandleHelp();




  • 相关阅读:
    POJ2778 DNA Sequence AC自动机上dp
    codeforces732F Tourist Reform 边双联通分量
    codeforces786B Legacy 线段树优化建图
    洛谷P3588 PUS 线段树优化建图
    codeforces1301D Time to Run 模拟
    codeforces1303B National Project 二分或直接计算
    codeforces1303C Perfect Keyboard 模拟或判断欧拉路
    codeforces1303D Fill The Bag 二进制应用+贪心
    python之路——使用python操作mysql数据库
    python之路——mysql索引原理
  • 原文地址:https://www.cnblogs.com/boydfd/p/4983125.html
Copyright © 2011-2022 走看看