(learn&think)

不浮躁,不自傲,学习,思考,总结

浅谈设计模式十九: 责任链模式(Chain of Responsibility)

| Comments

1 实例

学校里,教师,主管,主任都有不同的职责,现在家长有不同的请求,比如他们小孩的日常表现或付学费等,但家长并不清楚学校内部的职责归属,哪个请求该去找那个人处理,家长一般直接与孩子的老师交流,那么如何满足家长不同的请求呢?

2 责任链模式(Chain of Responsibility)

2.1 目的

避免请求的发送者通过给予多个对象机会去处理这个请求的方式到它的接收者的耦合。把接收对象组成一条链路,并把这个请求沿着这条链路传送直到一个对象处理它。

2.2 实现

利用责任链模式把处理者串起来,如果这个具体处理者能处理这个请求,它就处理它,否则它传递这个请求给它的后继对象。代码实例在这里

2.3 抽象处理者类

  1. 为处理请求定义一个接口。
  2. 维护后继者的引用
class Staff {
 public:
  virtual ~Staff() {}
  void set_name(string name) {name_ = name;}
  string name() {return name_;}
  void set_boss(Staff *boss) {boss_ = boss;}
  Staff* boss() {return boss_;}
  virtual void ProcessRequest(Request *a_request) = 0;
 protected:
  string name_;
  Staff *boss_;
};

2.4 请求类

请求分为不同的等级,来被不同职位的人处理.这里分为低,中和高三个等级,分别被老师,主管和主任处理.

enum ResponsiableLevel {
  kLow,
  kMedium,
  kHigh
};

class Request {
 public:
  virtual ~Request() {}
  void set_level(ResponsiableLevel level) {level_ = level;}
  ResponsiableLevel level() {return level_;}
  void set_description(string description) {description_ = description;}
  string description() {return description_;}
 private:
  string description_;
  ResponsiableLevel level_;
};

2.5 具体处理类

这里分为老师,主管和主任.

void Teacher::ProcessRequest(Request *a_request) {
  if (a_request->level() == kLow) {
    cout << "This is " << name_ << ". I am a teacher of this daycare. " <<
        "Your request has been approved!" << endl;
  } else {
    if (boss_ != NULL) {
      cout << "This is " << name_ << ". I am a teacher of this daycare. " <<
          " I am not able to process your request. " << "My boss " <<
          boss_->name() << "will review your request" << endl;
      boss_->ProcessRequest(a_request);
    } else {
      cout << "No boss assigned" << endl;
    }
  }
}

void Manager::ProcessRequest(Request *a_request) {
  if (a_request->level() == kMedium) {
    cout << "This is " << name_ << ". I am a manager of this daycare. " <<
        "Your request has been approved!" << endl;
  } else {
    if (boss_ != NULL) {
      cout << "This is " << name_ << ". I am a manager of this daycare. " <<
          " I am not able to process your request. " << "My boss " <<
          boss_->name() << "will review your request" << endl;
      boss_->ProcessRequest(a_request);
    } else {
      cout << "No boss assigned" << endl;
    }
  }
}

void Director::ProcessRequest(Request *a_request) {
  if (a_request->level() == kHigh) {
    cout << "This is " << name_ << ". I am a director of this daycare. " <<
        "Your request has been approved!" << endl;
  } else {
    if (boss_ != NULL) {
      cout << "This is " << name_ << ". I am a director of this daycare. " <<
          " I am not able to process your request. " << "My boss " <<
          boss_->name() << "will review your request" << endl;
      boss_->ProcessRequest(a_request);
    } else {
      cout << "No boss assigned" << endl;
    }
  }
}

3 总结

3.1 责任链模式(Chain of Responsibility)结构

3.2 组成

  • 处理者(Handler)
    1. 为处理请求定义一个接口。
    2. (可选)实现后继链接。
  • 具体处理者(ConcreteHandler)
    1. 处理它负责的请求。
    2. 能访问它的后继对象。
    3. 如果这个具体处理者能处理这个请求,它就处理它,否则它传递这个请求给它的后继对象。
  • 对象(Client)初始给链路中的具体处理者一个请求。

3.3 应用场景

  • 多余一个对象要处理一个请求,并且处理者不是先验的。处理者需要自动被弹探知。
  • 你想促发促一个请求给许多个对象之一并且不想明确指定哪个接收者时。
  • 处理请求的一组对象需要被动态指定。

3.4 缺点

收到不能被保证。因为一个请求没有明确的接收者,所以不能保证它将被处理——请求也能落到链路的末端而未曾被处理。一个请求也能不被处理当链路没有被合理的配置。

Comments