职责链模式 X 简化连接 X 加薪流程

职责链模式:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递 该请求,知道有一个对象处理它为止[DP]。

在模式结构图中,结合上面的文字,不难想象:Client是和Handler相关的,它构造了Handler对象(main函数作为Client),所以它们之间是关联关系(实现实心箭头);Handler提供接口,ConcreteHandler提供具体的处理请求方法,所以它们之间是继承关系;此外,Handler需要提供SetSuccessor接口,好让每个ConcreteHandler知道自己的后继者。所以,ConcreteHandler和Handler之间有聚合关系:在每个Handler对象中必须提供一个成员,用以保存“后继处理者”的地址(作为protected成员,Handler保存ConcreteHandler;这类似于“雁群”聚合了“大雁”个体一样:在雁群类中,保存了大雁个体对象的地址,作为成员)。

下面看看代码:

  1. #include <iostream>
  2. using namespace std;
  3. class Handler
  4. {
  5. protected:
  6.     Handler* m_Handler;
  7. public:
  8.     Handler():m_Handler(NULL){}
  9.     virtual void setSuccessor(Handler* p)
  10.     {
  11.         m_Handler = p;
  12.     }
  13.     virtual void HandlerRequest(int request)=0;
  14. };
  15. class ConcreteHandler1 : public Handler
  16. {
  17. public:
  18.     void HandlerRequest(int request)
  19.     {
  20.         //满足条件则处理
  21.         if (request==10)
  22.         {
  23.             cout<<"ConcreteHandler1处理请求"<<endl; 
  24.         }
  25.         else if (m_Handler!=NULL)
  26.         {
  27.             //让后继者处理
  28.             m_Handler->HandlerRequest(request);
  29.         }
  30.         else
  31.             cout<<"没人能处理了!"<<endl;
  32.     }
  33. };
  34. class ConcreteHandler2 : public Handler
  35. {
  36. public:
  37.     void HandlerRequest(int request)
  38.     {
  39.         //满足条件则处理
  40.         if (request==20)
  41.         {
  42.             cout<<"ConcreteHandler2处理请求"<<endl; 
  43.         }
  44.         else if (m_Handler!=NULL)
  45.         {
  46.             //让后继者处理
  47.             m_Handler->HandlerRequest(request);
  48.         }
  49.         else
  50.             cout<<"没人能处理了!"<<endl;
  51.     }
  52. };
  53. void main()
  54. {
  55.     Handler* h1 = new ConcreteHandler1();
  56.     Handler* h2 = new ConcreteHandler2();
  57.     h1->setSuccessor(h2);
  58.     int request=20;
  59.     h1->HandlerRequest(request);
  60.     request = 30;
  61.     h1->HandlerRequest(request);
  62. };

    很简单吧?需要注意的是C++里面Handler的构造函数咯!如果不将m_Handler设为0的话,会运行出错(因为里面包含的是一个随机数,not NULL)。

    职责链的好处:每个对象只需要保持一个指向其后继者的引用,而不需要保持所有候选接收者的引用;降低了耦合度。我们可以随时增加或修改一个请求的结构,增强给对象指派职责的灵活性。

    需要担心的是:一个请求极可能到了链末端都没有得到处理,或者因为没有正确配置而得不到正确的处理[1]!

    我们来重构一下加薪流程的代码例子:程序员将请求提交给总监,然后总监提交给管理者......层层上报。管理者类自己聚合自己,也就是要保存一个自己上级的指针,它的子类:经理、总监,负责“申请请求”;这些子类和“申请”类之间是依赖关系:子类虚线实心箭头指向申请类,因为Request作为子类函数的参数。

    还是看看下面的实现代码吧,感觉写得不够好,习惯用指针了:

 

  1. #include <iostream>
  2. #include <string>
  3. using namespace std;
  4. class Request
  5. {
  6. private:
  7.     //申请类别
  8.     string requestType;
  9. public:
  10.     string RequestType()
  11.     {
  12.         return requestType;
  13.     }
  14.     //申请内容
  15. private:
  16.     string requestContent;
  17. public:
  18.     string RequestContent()
  19.     {
  20.         return requestContent;
  21.     }
  22. public:
  23.     Request(string lhs,string rhs):requestType(lhs),requestContent(rhs){}
  24. };
  25. class Manager
  26. {
  27. protected:
  28.     string name;
  29.     Manager* superior;  //管理者的上级
  30. public:
  31.     Manager(string name):name(name),superior(NULL){}
  32.     //设置管理者的上级
  33.     void setSuperior(Manager* pSuperior)
  34.     {
  35.         superior=pSuperior;
  36.     }
  37.     virtual void requestApplication(Request& request)=0;
  38. };
  39. class CommonManager : public Manager
  40. {
  41. public:
  42.     CommonManager(string name):Manager(name){   }
  43.     void requestApplication(Request& request)
  44.     {
  45.         if (request.RequestType()=="请假")
  46.         {
  47.             cout<<name<<": "<<request.RequestContent()<<"被批准"<<endl;
  48.         }
  49.         else
  50.         {
  51.             //传递给上级
  52.             if (superior!=NULL)
  53.                 superior->requestApplication(request);
  54.             else
  55.                 cout<<"没人可以批准啦!"<<endl;
  56.         }
  57.     }
  58. };
  59. //总经理
  60. class GeneralManager : public Manager
  61. {
  62. public:
  63.     GeneralManager(string name):Manager(name){  }
  64.     void requestApplication(Request& request)
  65.     {
  66.         if(request.RequestType()=="加薪")
  67.             cout<<name<<": "<<request.RequestContent()<<"被批准"<<endl;
  68.         else
  69.         {
  70.             if (superior!=NULL)
  71.             {
  72.                 superior->requestApplication(request);
  73.             }
  74.             else
  75.                 cout<<"没人可以批准啦!"<<endl;
  76.         }
  77.     }
  78. };
  79. void main()
  80. {
  81.     Request request1("请假","yathing请假");
  82.     Request request2("加薪","yathing请求加薪");
  83.     CommonManager aCommonManager("老熊");
  84.     GeneralManager aGeneralManager("院长");
  85.     aCommonManager.setSuperior(&aGeneralManager);
  86.     aCommonManager.requestApplication(request1);
  87.     aCommonManager.requestApplication(request2);
  88. };

    很有意思吧!

[1] 试想:A类和B类都处理request==10的情况,A对象在B的前面,那么B就得不到处理机会了;如果实际处理情况更加复杂一些:B处理A一些比A更严格的条件,那我在增添一个B类的时候,还要考虑:我当前设置是否合理?会不会消息还没有传递到B这里,就已经被A处理(拦截)了?这样的结果可不是我想要的呢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值