zoukankan      html  css  js  c++  java
  • 责任链模式

    1.概述

      在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。

    2.纯责任链模式与不纯责任链模式

      

      一个纯的责任链模式要求一个具体的处理者对象只能在两个行为中选择一个:一是承担责任,而是把责任推给下家。不允许出现某一个具体处理者对象在承担了一部分责任后又 把责任向下传的情况。

      在一个纯责任链模式里,一个请求必须被某一个处理者对象所接收;在一个不纯的责任链模式里面,一个请求可以最终不被任何接收端对象所接收。

      纯的责任链模式的实际例子很难找到,一般看到的例子均是不纯的责任链模式的实现。有些人认为不纯的责任链根本不是责任链模式,这也许是有道理的。但是在实际的系统里,纯的责任链很难找到。如果坚持责任链不纯便不是责任链模式,那么责任链模式便不会有太大意义了。

    3.优缺点

    优点:

      1) 职责链模式使得一个对象无须知道是其他哪一个对象处理其请求,对象仅需知道该请求会被处理即可,接收者和发送者都没有对方的明确信息,且链中的对象不需要知道链的结构,由客户端负责链的创建,降低了系统的耦合度。

      2) 请求处理对象仅需维持一个指向其后继者的引用,而不需要维持它对所有的候选处理者的引用,可简化对象的相互连接。

      3) 在给对象分派职责时,职责链可以给我们更多的灵活性,可以通过在运行时对该链进行动态的增加或修改来增加或改变处理一个请求的职责。

      4) 在系统中增加一个新的具体请求处理者时无须修改原有系统的代码,只需要在客户端重新建链即可,从这一点来看是符合“开闭原则”的。

    缺点:

      1) 由于一个请求没有明确的接收者,那么就不能保证它一定会被处理,该请求可能一直到链的末端都得不到处理;一个请求也可能因职责链没有被正确配置而得不到处理。

      2) 对于比较长的职责链,请求的处理可能涉及到多个处理对象,系统性能将受到一定影响,而且在进行代码调试时不太方便。

      3) 如果建链不当,可能会造成循环调用,将导致系统陷入死循环。

    4.适用场景

    在以下情况下可以考虑使用职责链模式:

      1) 有多个对象可以处理同一个请求,具体哪个对象处理该请求待运行时刻再确定,客户端只需将请求提交到链上,而无须关心请求的处理对象是谁以及它是如何处理的。

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

      3) 可动态指定一组对象处理请求,客户端可以动态创建职责链来处理请求,还可以改变链中处理者之间的先后次序。

      以上,参考http://blog.csdn.net/lovelion/article/details/7420902 

    5.代码

      

      1 #include "stdafx.h"
      2 #include <iostream>
      3 #include <string>
      4 using namespace std;
      5 
      6 // 请求
      7 class Request
      8 {
      9 public:
     10   int m_nNumber;
     11 };
     12 
     13 // 管理者
     14 class Manager
     15 {
     16 public:
     17   Manager(string temp) { name = temp; }
     18   void SetSuccessor(Manager* temp) { manager = temp; }
     19   virtual void GetRequest(Request* request) = 0;
     20 protected:
     21   Manager* manager;
     22   string name;
     23 };
     24 
     25 // 经理
     26 class CommonManager : public Manager
     27 {
     28 public:
     29   CommonManager(string strTemp) : Manager(strTemp) {}
     30   virtual void GetRequest(Request* request)
     31   {
     32     if (request->m_nNumber>=0 && request->m_nNumber<1000)
     33     {
     34       cout << name << " 处理了请求: " << request->m_nNumber << endl;
     35     }
     36     else
     37     {
     38       manager->GetRequest(request);
     39     }
     40   }
     41 };
     42 
     43 // 总监
     44 class Majordomo : public Manager
     45 {
     46 public:
     47   Majordomo(string strTemp) : Manager(strTemp) {}
     48   virtual void GetRequest(Request* request)
     49   {
     50     if (request->m_nNumber <= 5000)
     51     {
     52       cout << name << " 处理了请求: " << request->m_nNumber << endl;
     53     }
     54     else
     55     {
     56       manager->GetRequest(request);
     57     }
     58   }
     59 };
     60 
     61 //总经理  
     62 class GeneralManager: public Manager  
     63 {  
     64 public:  
     65   GeneralManager(string name):Manager(name) {}  
     66   virtual void GetRequest(Request* request)  //总经理可以处理所有请求  
     67   {         
     68     cout << name << " 处理了请求: " << request->m_nNumber << endl;
     69   }  
     70 };
     71 
     72 int main()
     73 {
     74   Manager* common = new CommonManager("张经理");
     75   Manager* major = new Majordomo("李总监");
     76   GeneralManager* general  = new GeneralManager("赵总");
     77   // common对象的SetSuccessor函数中传递major对象的引用,
     78   // 当common对象能够处理时就处理,不能处理时传递给major对象处理
     79   // 同样majar对象的SetSuccessor函数中传递general对象的引用
     80   // 当majar对象能够处理时就处理,不能处理时传递给general对象处理
     81   common->SetSuccessor(major);
     82   major->SetSuccessor(general);
     83   Request* rq = new Request();
     84 
     85   rq->m_nNumber = 999;
     86   common->GetRequest(rq);
     87 
     88   rq->m_nNumber = 4999;
     89   common->GetRequest(rq);
     90 
     91   rq->m_nNumber = 6999;
     92   common->GetRequest(rq);
     93 
     94   delete rq;
     95   delete major;
     96   delete common;
     97   delete general;
     98 
     99   system("pause");
    100   return 0;
    101 }

     

  • 相关阅读:
    java 单例模式
    java 设计模式
    android 设计模式
    我的坦克兵爷爷也曾扬威世界
    我的坦克兵爷爷也曾扬威世界
    LD_LIBRARY_PATH设置问题
    LD_LIBRARY_PATH设置问题
    销售员和程序员
    销售员和程序员
    如何成为Python高手
  • 原文地址:https://www.cnblogs.com/SnailProgramer/p/4274825.html
Copyright © 2011-2022 走看看