服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > JAVA > 高级技术 > 设计模式 > 查看文档

责任链模式(chain of responsibility)


  描述:
  
  责任链模式(cor)建议发出请求的对象与可能处理这个请求的对象集合之间是低耦合的(set of potential request handler objects)。
  
  在有不止一个对象可以处理或实现(fulfill)客户请求的时候,责任链模式(cor)认为顺序地给每一个对象一次处理请求的机会。在这种情况下应用责任链模式(cor),把每一个可能处理请求的对象以链表的形式组织起来,在链表中,每一个对象有一个指向下一个对象的指针(pointer)。在链表中的第一个对象接受请求并且决定是否处理它,或者把它传递
  
  给下一个对象。请求一个接一个地遍历(flow through)链表中的所有对象,直到请求被其中的一个对象处理或者因到达链表尾而没有被处理。
  
  例如:如果a?〉b?〉c都可以处理请求,按照这个顺序,a处理请求或者在不知b是否可以处理这个请求的情况下递给b。接受到请求的b可以处理这个请求或者传递给c。
  
  当c收到请求时,这个请求可以被c处理或者没有经过任何处理而结束。换句话说,提交的处理链表中的请求在到达链表尾前,可以不被任何处理。
  
  下面是责任链模式(cor)一些重要的特征:
  
  (1)  可能处理请求的对象集合(set of potential request handler objects)以及它们在链表中的顺序是由客户端根据现应用的状态在运行时动态决定的。
  
  (2)  客户端根据现在的状态,对于不同的请求类型,可以拥有不同的可能处理请求的对象集合(set of potential request handler objects)。一个处理请求的对象也可以根据客户应用的状态和请求类型,把请求传递给不同的处理对象。为了使这些交互简单,所有的可能处理请求的对象应提供一致的接口。在java中,不同处理对象可以实现一个共同的接口或者继承同一个抽象的父类来实现。
  
  (3)  客户对象初始化请求,或者在不知道这些对象是否能处理这个请求的情况下初始化任何可能处理请求的对象。也就是说,客户对象和在处理链表中的处理对象都不需要知道到底哪个对象去处理这个请求。
  
  (4)  请求不能保证被处理。也就是,在没有处理的情况下,请求已经到达了处理链表尾。下面的这个情景展示了一个购买请求传递到处理链表中,但是在到达链表尾时,并没有被接受。
  
  例子:
  
  让我们模拟一个在特定组织里的购买请求(pr)授权过程的应用。通常,在确立订单并发到卖方前,一个购买请求是需要不同的管理代表授权的。我们假定一个组织中在购买请求金额限制上分为四个授权管理层次,如下面的列表:
  
  table 21.1: levels of pr authorization
  management level   authorization limit
  branch manager  $25,000
  regional director  $100,000
  vice president  $200,000
  president and coo  $400,000
  
 

  我们可以定义不同的类,来对应上面列表中的不同管理层次。
  listing 21.1: classes representing different management levels
  
  class branchmanager {
  static double limit = 25000;
  …
  …
  }//end of class
  class regionaldirector {
  static double limit = 100000;
  …
  …
  }//end of class
  class vicepresident {
  static double limit = 200000;
  …
  …
  }//end of class
  class presidentcoo {
  static double limit = 400000;
  …
  …
  }//end of class
  
  让我们定义一个purchaserequest类,它代表购买请求。
  
  purchaserequest
  id:int
  description:string
  amount:double
  getamount():double
  
 

  figure 21.1: purchaserequest class representation
  
  listing 21.2: purchaserequest class
  
  class purchaserequest {
  private int id;
  private string description;
  private double amount;
  public purchaserequest(int id, string desc, double amt) {
  id = id;
  description = desc;
  amount = amt;
  }
  public double getamount() {
  return amount;
  }
  public string tostring() {
  return id + ":" + description;
  }
  }
  
  一个给定的购买请求(pr)被上面的管理代表所授权或处理。换句话说,代表不同管理层次的四个类都是处理给定购买请求的可能处理者(授权者)。因此,不建议purchaserequest实例榜定到任何的一个授权者。通过使用责任链模式(cor),实现了purchaserequest对象和可能授权请求的对象集合之间关联的低耦合。
  
  利用责任链模式(cor),让我们定义一个抽象类prhandler,它定义这些可能授权购买请求对象的统一接口。
  
  listing 21.3: abstract prhandler class
  
  public abstract class prhandler {
  private prhandler nexthandler;
  private string handlername;
  public prhandler(string name) {
  handlername = name;
  }
  public string getname() {
  return handlername;
  }
  public abstract boolean authorize(purchaserequest request);
  public prhandler getnexthandler() {
  return nexthandler;
  }
  public void setnexthandler(prhandler handler) {
  nexthandler = handler;
  };
  }
  
 

  figure 21.2: purchase request approver hierarchy
  
  现在,每一个授权者被重新定义为抽象类prhandler的子类。每一个授权对象把购买请求的金额和它所在的管理层次所授权的金额进行比较,如果请求的金额小于授权的金额,它就可以授权购买,如果大于,它传递购买请求到链表中的下一个授权者。
  
  listing 21.4: prhandler concrete subclasses
  
  class branchmanager extends prhandler {
  static double limit = 25000;
  public branchmanager(string name) {
  super(name);
  }
  public boolean authorize(purchaserequest request) {
  double amount = request.getamount();
  if (amount <= limit) {
  system.out.println(" branch manager " + getname() +
  " has authorized the pr ? " + request);
  return true;
  } else {
  //forward the request to the next handler
  return getnexthandler().authorize(request);
  }
  }
  }//end of class
  class regionaldirector extends prhandler {
  static double limit = 100000;
  public regionaldirector(string name) {
  super(name);
  }
  public boolean authorize(purchaserequest request) {
  double amount = request.getamount();
  if (amount <= limit) {
  system.out.println(" regional director " + getname() +
  " has authorized the pr ? " +
  request);
  return true;
  } else {
  //forward the request to the next handler
  return getnexthandler().authorize(request);
  }
  }
  }//end of class
  class vicepresident extends prhandler {
  static double limit = 200000;
  public vicepresident(string name) {
  super(name);
  }
  public boolean authorize(purchaserequest request) {
  double amount = request.getamount();
  if (amount <= limit) {
  system.out.println(" v.p. " + getname() +
  " has authorized the pr ? " + request);
  return true;
  } else {
  //forward the request to the next handler
  return getnexthandler().authorize(request);
  }
  }
  }//end of class
  class presidentcoo extends prhandler {
  static double limit = 400000;
  public presidentcoo(string name) {
  super(name);
  }
  public boolean authorize(purchaserequest request) {
  double amount = request.getamount();
  if (amount <= limit) {
  system.out.println(" president & coo " + getname() +
  " has authorized the pr ? " + request);
  return true;
  } else {
  system.out.println("pr ? " + request +
  " couldn't be authorized.\n " +
  "executive board needs to be " +
  "consulted for approval \n" +
  "reason: amount too large");
  return false;
  }
  }
  }//end of class
  
  为了授权购买请求,客户端需要:
  
  (1)  创建一个可能接受购买请求的授权对象集合,把他们按照授权金额升序进行排列,使用setnexthandler(prhandler)方法,连接每一个授权者。下面是可能的授权购买请求的授权链表:
  
 

  figure 21

扫描关注微信公众号