您的位置:首页 > 大数据 > 人工智能

Chain Of Responsibility Design Pattern Example

2014-03-14 16:58 411 查看
Avoid coupling thesender of a request to thereceiver by giving more than one object a chance to handle therequest. Chain thereceiving objects and pass therequest along thechain until an object handles it.

The main intention in Chain Of Responsibility is to decouple theorigin of therequest and thehandling of therequest such that theorigin of therequest need not worry who and how its request is being handled as long as it gets theexpected outcome. By decoupling theorigin of therequest and therequest handler we make sure that both can change easily and new request handlers can be added without theorigin of therequest i.e client being aware of thechanges. 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 therequest from theclient. All theobjects which are part of thechain are created from classes which confirm to a common interface there by theclient only needs to be aware of theinterface and not necessarily thetypes of its implementations. The client assigns therequest to first object part of thechain and thechain is created in such a way that there would be atleast one object which can handle therequest or theclient would be made aware of thefact 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 theformat of thefile being passed to theparser, theparser has to decide whether its going to parse thefile or pass therequest 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 therequest for which file. We then populate file names of different formats into a list and then iterate through them passing thefile name to thefirst parser in thelist.

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



The Java code for thesame 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 tofind thecorrect parserfor thefile: '
+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 theParser class and override theparse method. I have kept theimplementation of different parser simple and these methods evaluate if thefile has theformat they are looking for. If a particular handler is unable to process therequest i.e. thefile format is not what it is looking for then theparent method handles such requests. The handler method in theparent class just invokes thesame method on thesuccessor 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 thefile: '
+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 thefile: '
+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 thefile: '
+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 thefile: '
+fileName);
07
}
08
else
{
09
super
.parse(fileName);
10
}
11
}
12
13
}
Now that we have all thehandlers setup, we need to create a chain of handlers. In this example thechain we create is: TextParser-> JsonParser-> CsvParser-> XmlParser. And if XmlParseris unable to handle therequest then theParser class throws out a message stating that therequest was not handled. Lets see thecode for theclient class which creates a list of files names and then creates thechain 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 thelast in chain.
15
Parser xmlParser =
new
XmlParser();
16
17
//XmlParseris thesuccessor of CsvParser.
18
Parser csvParser =
new
CsvParser(xmlParser);
19
 
20
//CsvParseris thesuccessor of JsonParser.
21
Parser jsonParser =
new
JsonParser(csvParser);
22
 
23
//JsonParseris thesuccessor of TextParser.
24
//TextParseris thestart of thechain. 
25
Parser textParser =
new
TextParser(jsonParser);
26
 
27
//Pass thefile name to thefirst handler in thechain.
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 thefile name list above I have intentionally added a file name for which there is no handler created. Running theabove code gives us theoutput:

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
thecorrect 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 theExperiences Unlimited blog.

You might also like:

Chain of Responsibility Pattern in Java

Chain of responsibility using Spring @Autowired List

Memento Design Pattern in Java – Example Tutorial
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: