现在的位置: 首页 > 综合 > 正文

职责链模式

2014年06月25日 ⁄ 综合 ⁄ 共 6749字 ⁄ 字号 评论关闭

先看经典职责链代码, 

(代码来自维基) 

Java代码  收藏代码
  1. package pattern;  
  2.   
  3. import java.io.*;  
  4.   
  5. abstract class PurchasePower {  
  6.   
  7.     protected final double base = 500;  
  8.     protected PurchasePower successor;  
  9.   
  10.     public void setSuccessor(PurchasePower successor) {  
  11.         this.successor = successor;  
  12.     }  
  13.   
  14.     abstract public void processRequest(PurchaseRequest request);  
  15. }  
  16.   
  17. class ManagerPPower extends PurchasePower {  
  18.     private final double ALLOWABLE = 10 * base;  
  19.   
  20.     public void processRequest(PurchaseRequest request) {  
  21.         if (request.getAmount() < ALLOWABLE)  
  22.             System.out.println("Manager will approve $" + request.getAmount());  
  23.         else if (successor != null)  
  24.             successor.processRequest(request);  
  25.     }  
  26. }  
  27.   
  28. class DirectorPPower extends PurchasePower {  
  29.     private final double ALLOWABLE = 20 * base;  
  30.   
  31.     public void processRequest(PurchaseRequest request) {  
  32.         if (request.getAmount() < ALLOWABLE)  
  33.             System.out.println("Director will approve $" + request.getAmount());  
  34.         else if (successor != null)  
  35.             successor.processRequest(request);  
  36.     }  
  37. }  
  38.   
  39. class VicePresidentPPower extends PurchasePower {  
  40.     private final double ALLOWABLE = 40 * base;  
  41.   
  42.     public void processRequest(PurchaseRequest request) {  
  43.         if (request.getAmount() < ALLOWABLE)  
  44.             System.out.println("Vice President will approve $"  
  45.                     + request.getAmount());  
  46.         else if (successor != null)  
  47.             successor.processRequest(request);  
  48.     }  
  49. }  
  50.   
  51. class PresidentPPower extends PurchasePower {  
  52.     private final double ALLOWABLE = 60 * base;  
  53.   
  54.     public void processRequest(PurchaseRequest request) {  
  55.         if (request.getAmount() < ALLOWABLE)  
  56.             System.out  
  57.                     .println("President will approve $" + request.getAmount());  
  58.         else  
  59.             System.out.println("Your request for $" + request.getAmount()  
  60.                     + " needs a board meeting!");  
  61.     }  
  62. }  
  63.   
  64. class PurchaseRequest {  
  65.   
  66.     private int number;  
  67.     private double amount;  
  68.     private String purpose;  
  69.   
  70.     public PurchaseRequest(int number, double amount, String purpose) {  
  71.         this.number = number;  
  72.         this.amount = amount;  
  73.         this.purpose = purpose;  
  74.     }  
  75.   
  76.     public double getAmount() {  
  77.         return amount;  
  78.     }  
  79.   
  80.     public void setAmount(double amt) {  
  81.         amount = amt;  
  82.     }  
  83.   
  84.     public String getPurpose() {  
  85.         return purpose;  
  86.     }  
  87.   
  88.     public void setPurpose(String reason) {  
  89.         purpose = reason;  
  90.     }  
  91.   
  92.     public int getNumber() {  
  93.         return number;  
  94.     }  
  95.   
  96.     public void setNumber(int num) {  
  97.         number = num;  
  98.     }  
  99. }  
  100.   
  101. public class CheckAuthority {  
  102.     public static void main(String[] args) {  
  103.         ManagerPPower manager = new ManagerPPower();  
  104.         DirectorPPower director = new DirectorPPower();  
  105.         VicePresidentPPower vp = new VicePresidentPPower();  
  106.         PresidentPPower president = new PresidentPPower();  
  107.         manager.setSuccessor(director);  
  108.         director.setSuccessor(vp);  
  109.         vp.setSuccessor(president);  
  110.   
  111.         // enter ctrl+c to kill.  
  112.         try {  
  113.             while (true) {  
  114.                 System.out  
  115.                         .println("Enter the amount to check who should approve your expenditure.");  
  116.                 System.out.print(">");  
  117.                 double d = Double.parseDouble(new BufferedReader(  
  118.                         new InputStreamReader(System.in)).readLine());  
  119.                 manager.processRequest(new PurchaseRequest(0, d, "General"));  
  120.             }  
  121.         } catch (Exception e) {  
  122.             System.exit(1);  
  123.         }  
  124.     }  
  125. }  



这段代码实现了不同审批限额由不同级别的人去审批的功能。 

该模式有如下特点: 

1. 几个对象组成链表结构,用来向后传递请求; 
2. 请求被处理,则返回;否则继续向后传递;(有的实现则是不论请求是否被处理,都向后传递)。 
3. 对象都继承自同一个父类或实现了共同的用来处理请求的接口。 

优点: 

1. 发起者(调用者)与接收者分离。 
2. 可动态插入职责链。 

缺点: 

1. 遍历链表有性能损耗。 

职责链模式的经典应用是Servlet中的的Filter技术。略过Filter的很简单的使用 
方法,我们来看看它在tomcat中的实现。为了说明方便,这里只是它的实现的一 
个简化演示代码。 

用户自定义的filter都需实现了如下的Filter接口, 

doFilter(ServletRequest request,ServletResponse response,FilterChain chain)throws java.io.IOException,ServletException 

用户在这个接口里写的代码可以截获请求。对截获的请求处理后,可以把处理权 
传递给下一个filter。传递给下一个filter的方法是调用如下一行代码, 

chain.doFilter(request,response); 

这行代码是Servlet里的Filter技术的核心,所以接下来我们主要就是分析、模拟 
这行代码做了什么,它是如何把请求传递给下一个filter的,下一个filter是何 
时被创建的。 

下面是对整个过程的简单模拟。很简单,就是读配置文件,生成多个 
ApplicationFilterConfig对象(称呼它为配置对象),该配置对象负责生成 
filter对象。 

Java代码  收藏代码
  1. final class ApplicationFilterChain implements FilterChain {  
  2.     private List filterConfigs = new ArrayList();  
  3.     private Iterator iterator = null;  
  4.   
  5.     public void doFilter(ServletRequest request, ServletResponse response) {  
  6.         if (this.iterator == null)  
  7.             this.iterator = filters.iterator();  
  8.   
  9.         if (this.iterator.hasNext()) {  
  10.             ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) iterator  
  11.                     .next();// 在这里取得下一个filter的配置对象  
  12.             Filter filter = filterConfig.getFilter();// 注意:在这里取得了下一个filter,这个filter就是你实现了filter接口的filter.  
  13.             filter.doFilter(request, response, this);// 把请求传递个下一个filter处理  
  14.         }  
  15.     }  
  16.   
  17.     public void startFilter() {  
  18.         ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) iterator  
  19.                 .next();  
  20.         Filter filter = filterConfig.getFilter();  
  21.         filter.doFilter(request, response, this);  
  22.     }  
  23.   
  24.     public void addFilterConfig(ApplicationFilterConfig filterConfig) {  
  25.         filterConfigs.add(filterConfig);  
  26.     }  
  27. }  
  28.   
  29. final class ApplicationFilterConfig implements FilterConfig {  
  30.     private Filter filter = null;  
  31.     private String filterClass;  
  32.   
  33.     public Filter getFilter() {  
  34.         if (this.filter != null)  
  35.             return (this.filter);  
  36.   
  37.         Class clazz = classLoader.loadClass(filterClass);  
  38.         this.filter = (Filter) clazz.newInstance();  
  39.         return this.filter;  
  40.     }  
  41. }  
  42.   
  43. public class MainTest {  
  44.     public FilterChain create() {  
  45.         ApplicationFilterChain a = new ApplicationFilterChain();  
  46.         List filters = readConfigFile();// 读取配置文件,获取filter信息,实现过程略  
  47.         for (int i = 0; i < filters.size(); i++) {  
  48.             ApplicationFilterConfig afc = (ApplicationFilterConfig) filters  
  49.                     .get(i);  
  50.             a.addFilterConfig(afc);  
  51.         }  
  52.         return a;  
  53.     }  
  54.   
  55.     public static void main(String args[]) {  
  56.         (new MainTest()).create().startFilter();  
  57.     }  
  58. }  



tomcat的chain实现有3个要点, 

1. 不是一下子全部初始化所有的filter对象,而是只初始化所有的配置对象。配 
置对象的生成比filter对象的生成节省资源,生成配置对象只是存储了一些配置 
信息。filter对象的生成需要反射,相对消耗资源。 

2. 在第一次调用filter的时候,由配置对象生成filter对象。下一次再次调用则 
直接使用已经生成的filter对象。缓存思路。 

3. 由FilterChain维护一个链表,链表中存放着配置对象的链条,每次用户调用 
一次chain.doFilter(req, res),链表就去取下一个配置对象,再通过配置对象 
得到下一个filter,然后调用该filter,接着你在filter里写的逻辑就被执行了。 

抱歉!评论已关闭.