Avoid coupling the sender of a request to the receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.

The main intention in Chain Of Responsibility is to decouple the origin of the request and the handling of the request such that the origin of the request need not worry who and how its request is being handled as long as it gets the expected outcome. By decoupling the origin of the request and the request handler we make sure that both can change easily and new request handlers can be added without the origin of the request i.e client being aware of the changes. In this pattern we create a chain of objects such that each object will have a reference to another object which we call it as successor and these objects are responsible for handling the request from the client. All the objects which are part of the chain are created from classes which confirm to a common interface there by the client only needs to be aware of the interface and not necessarily the types of its implementations. The client assigns the request to first object part of the chain and the chain is created in such a way that there would be atleast one object which can handle the request or the client would be made aware of the fact that its request couldn’t be handled.

With this brief introduction I would like to put forth a very simple example to illustrate this pattern. In this example we create a chain of file parsers such that depending on the format of the file being passed to the parser, the parser has to decide whether its going to parse the file or pass the request to its successor parser to take action. The parser we would chain are: Simple text file parser, JSON file parser, CSV file parser and XML file parser. The parsing logic in each of these parser doesn’t parse any file, instead it just prints out a message stating who is handing the request for which file. We then populate file names of different formats into a list and then iterate through them passing the file name to the first parser in the list.

Lets define the Parser class, first let me show the class diagram for Parser class:

The Java code for the same is:

01 public class Parser {
02    
03   private Parser successor;
04    
05   public void parse(String fileName){
06     if ( getSuccessor() != null ){
07       getSuccessor().parse(fileName);
08     }
09     else{
10       System.out.println('Unable to find the correct parser for the file: '+fileName);
11     }
12   }
13    
14   protected boolean canHandleFile(String fileName, String format){
15     return (fileName == null) || (fileName.endsWith(format));
16          
17   }
18  
19   Parser getSuccessor() {
20     return successor;
21   }
22  
23   void setSuccessor(Parser successor) {
24     this.successor = successor;
25   }
26 }

We would now create different handlers for parsing different file formats namely- Simple text file, JSON file, CSV file, XML file and these extend from the Parser class and override the parse method. I have kept the implementation of different parser simple and these methods evaluate if the file has the format they are looking for. If a particular handler is unable to process the request i.e. the file format is not what it is looking for then the parent method handles such requests. The handler method in the parent class just invokes the same method on the successor handler.

The simple text parser:

01 public class TextParser extends Parser{
02  
03   public TextParser(Parser successor){
04     this.setSuccessor(successor);
05   }
06    
07   @Override
08   public void parse(String fileName) {
09     if ( canHandleFile(fileName, '.txt')){
10       System.out.println('A text parser is handling the file: '+fileName);
11     }
12     else{
13       super.parse(fileName);
14     }
15      
16   }
17  
18 }

The JSON parser:

01 public class JsonParser extends Parser {
02  
03   public JsonParser(Parser successor){
04     this.setSuccessor(successor);
05   }
06    
07   @Override
08   public void parse(String fileName) {
09     if ( canHandleFile(fileName, '.json')){
10       System.out.println('A JSON parser is handling the file: '+fileName);
11     }
12     else{
13       super.parse(fileName);
14     }
15  
16   }
17  
18 }

The CSV parser:

01 public class CsvParser extends Parser {
02  
03   public CsvParser(Parser successor){
04     this.setSuccessor(successor);
05   }
06    
07   @Override
08   public void parse(String fileName) {
09     if ( canHandleFile(fileName, '.csv')){
10       System.out.println('A CSV parser is handling the file: '+fileName);
11     }
12     else{
13       super.parse(fileName);
14     }
15   }
16  
17 }

The XML parser:

01 public class XmlParser extends Parser {
02    
03   @Override
04   public void parse(String fileName) {
05     if ( canHandleFile(fileName, '.xml')){
06       System.out.println('A XML parser is handling the file: '+fileName);
07     }
08     else{
09       super.parse(fileName);
10     }
11   }
12  
13 }

Now that we have all the handlers setup, we need to create a chain of handlers. In this example the chain we create is: TextParser -> JsonParser -> CsvParser -> XmlParser. And if XmlParser is unable to handle the request then the Parser class throws out a message stating that the request was not handled. Lets see the code for the client class which creates a list of files names and then creates the chain which I just described.

01 import java.util.List;
02 import java.util.ArrayList;
03  
04 public class ChainOfResponsibilityDemo {
05  
06   /**
07    * @param args
08    */
09   public static void main(String[] args) {
10      
11     //List of file names to parse.
12     List<String> fileList = populateFiles();
13      
14     //No successor for this handler because this is the last in chain.
15     Parser xmlParser = new XmlParser();
16  
17     //XmlParser is the successor of CsvParser.
18     Parser csvParser = new CsvParser(xmlParser);
19      
20     //CsvParser is the successor of JsonParser.
21     Parser jsonParser = new JsonParser(csvParser);
22      
23     //JsonParser is the successor of TextParser.
24     //TextParser is the start of the chain.
25     Parser textParser = new TextParser(jsonParser);
26      
27     //Pass the file name to the first handler in the chain.
28     for ( String fileName : fileList){
29       textParser.parse(fileName);
30     }
31  
32   }
33    
34   private static List<String> populateFiles(){
35      
36     List<String> fileList = new ArrayList<>();
37     fileList.add('someFile.txt');
38     fileList.add('otherFile.json');
39     fileList.add('xmlFile.xml');
40     fileList.add('csvFile.csv');
41     fileList.add('csvFile.doc');
42      
43     return fileList;
44   }
45  
46 }

In the file name list above I have intentionally added a file name for which there is no handler created. Running the above code gives us the output:

1 A text parser is handling the file: someFile.txt
2 A JSON parser is handling the file: otherFile.json
3 A XML parser is handling the file: xmlFile.xml
4 A CSV parser is handling the file: csvFile.csv
5 Unable to find the correct parser for the file: csvFile.doc

Happy coding and don’t forget to share!

Reference: Simple example to illustrate Chain Of Responsibility Design Pattern from our JCG partner Mohamed Sanaulla at the Experiences Unlimited blog.

Chain Of Responsibility Design Pattern Example的更多相关文章

  1. Design Patterns Uncovered: The Chain Of Responsibility Pattern

    Chain of Responsibility in the Real World The idea of the Chain Of Responsibility is that it avoids ...

  2. 深入浅出设计模式——职责链模式(Chain of Responsibility Pattern)

    模式动机 职责链可以是一条直线.一个环或者一个树形结构,最常见的职责链是直线型,即沿着一条单向的链来传递请求.链上的每一个对象都是请求处理者,职责链模式可以将请求的处理者组织成一条链,并使请求沿着链传 ...

  3. 二十四种设计模式:责任链模式(Chain of Responsibility Pattern)

    责任链模式(Chain of Responsibility Pattern) 介绍为解除请求的发送者和接收者之间耦合,而使多个对象都有机会处理这个请求.将这些对象连成一条链,并沿着这条链传递该请求,直 ...

  4. 乐在其中设计模式(C#) - 责任链模式(Chain of Responsibility Pattern)

    原文:乐在其中设计模式(C#) - 责任链模式(Chain of Responsibility Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 责任链模式(Chain of R ...

  5. C#设计模式之二十一职责链模式(Chain of Responsibility Pattern)【行为型】

    一.引言   今天我们开始讲"行为型"设计模式的第八个模式,该模式是[职责链模式],英文名称是:Chain of Responsibility Pattern.让我们看看现实生活中 ...

  6. 责任链模式 职责链模式 Chain of Responsibility Pattern 行为型 设计模式(十七)

    责任链模式(Chain of Responsibility Pattern) 职责链模式 意图 使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系 将这些对象连接成一条链,并沿着这 ...

  7. C#设计模式之二十职责链模式(Chain of Responsibility Pattern)【行为型】

    一.引言 今天我们开始讲“行为型”设计模式的第八个模式,该模式是[职责链模式],英文名称是:Chain of Responsibility Pattern.让我们看看现实生活中的例子吧,理解起来可能更 ...

  8. 19.职责链模式(Chain of Responsibility Pattern)

    19.职责链模式(Chain of Responsibility Pattern)

  9. Chain of Responsibility Pattern

    1.Chain of Responsibility模式:将可能处理一个请求的对象链接成一个链,并将请求在这个链上传递,直到有对象处理该请求(可能需要提供一个默认处理所有请求的类,例如MFC中的Cwin ...

随机推荐

  1. 02 - Unit010:关联映射

    关联映射 什么是? 数据库中有关联关系的表,通过实体对象引用的方式体现出来,叫关联映射. 为什么? 将多表的记录封装成实体对象. 何时用? 对数据库中的表进行多表查询时. 怎么用? cn_user-- ...

  2. javascript中不存在块级作用域,所以要小心使用在块级作用域中的函数声明所带来的作用域混乱.

    在javascript中函数的作用域是一个非常重要的概念. javascript中是没有块级作用域,但是有函数作用域的概念. 我们在开发的过程中,经常会遇到这样的问题, 某个函数我暂时不需要,不想声明 ...

  3. Spring中使用JDBC

    Spring中的数据库异常体系 使用JDBC(不使用Spring)的时候,我们需要强制捕获SQLException,否则无法使用JDBC处理任何事情.SQLException表示尝试访问数据库的时候出 ...

  4. usaco 2009 12 过路费

    最近学的图论,oj上的这道题卡了我一上午,写一下总结. 题目描述: 跟所有人一样,农夫约翰以着宁教我负天下牛,休教天下牛负我(原文:宁我负人,休教人负我)的伟大精神,日日夜夜苦思生财之道.为了发财,他 ...

  5. jquery使用js的一些疼处

    使用javascript的一些疼处 书写繁琐,代码量大 代码复杂 动画效果,很难实现.使用定时器 各种操作和处理 HTML <button id="btn">按钮< ...

  6. 浅谈Storm流式处理框架

    Hadoop的高吞吐,海量数据处理的能力使得人们可以方便地处理海量数据.但是,Hadoop的缺点也和它的优点同样鲜明——延迟大,响应缓慢,运维复杂. 有需求也就有创造,在Hadoop基本奠定了大数据霸 ...

  7. c# 二维码支持中文

    /// <summary> /// 生成二维码,保存成图片 /// </summary> static void Generate1(string text) { Barcod ...

  8. python greenlet 背景介绍与实现机制

    最近开始研究Python的并行开发技术,包括多线程,多进程,协程等.逐步整理了网上的一些资料,今天整理一下greenlet相关的资料. 并发处理的技术背景 并行化处理目前很受重视, 因为在很多时候,并 ...

  9. 人脸识别-<转>

    人脸检测库libfacedetection介绍 libfacedetection是于仕琪老师放到GitHub上的二进制库,没有源码,它的License是MIT,可以商用.目前只提供了windows 3 ...

  10. sass的类型判定

    由于sass的作者是rubyer,因此它的类型与JS有点不一样,但一样可以类推. @charset "utf-8";//必须设置了这个才能编译有中文的注释 $gray: #333; ...