设计模式之职责链
最近,在学习ajax的时候,发现了一个前后台传输数据的好东东:json,通过json字符串我们能很快的将java对象转换成javascript对象,至于json具体是什么东西,可以上他的官方网站去查看一下。这里简单的介绍一下: json用一对大括号来表示一个对象,并用冒号隔开属性和值,用逗号分隔多个属性。表示数组对象的时候json用一对中括号表示。如下:
1:json代码来表示一个对象: {"name":"杨川","sex":"男","age":26}.
这就表示了一个人的对象。 它的属性name = 杨川,性别=男 。年纪 =26岁。
2:json表示数组: [1,2,3,{"name":"sam","sex":"man"}].
这个就是一个数组, 其实熟悉javascript的人,都应该能看出来 json非常相似于javascript的直接量。比如数组直接量,对象直接量。
恩,到这里我简单介绍一下我要做的事情。是这样的,我们的javascript可以通过一个eval函数,将json字串转化成它自己的对象,比如上边的那个对象我们要穿换成 我们的 javascript对象就可以这样写
jsonText = " {'name':'杨川','sex':'男','age':26}"
var person = eval('('+jsonText+')'); //得到一个javascrip对象
alert(person.name) //提示: 杨川。
所以,我们只要在java服务端将pojo生成一个个的json字符串,在前台就可以 很简单的转换为js对象了。为前台的数据使用提供了很大的方便 。
因此我尝试写了这么一个转换工具包,结果,在编写的时候,发现职责链模式到时很适合这个。就拿来用了。呵呵,当然我下边的 代码不一定是唯一的,完善的,如果各位看客有更好的 思路和方法。还请赐教啊。
好了,言归正传了。
我对职责链的理解是这样的,在处理某些业务的时候,我们可能会判断不同的情况去选择做不同的业务处理,这样就可能导致大量的if else语句组出来。导致程序的扩展维护相当困难,就比如我这里转换json的这个例子,我的一个tojson(Object object)函数。他里边就要判断这样一些情况,如果是一个pojo则返回的字符串首尾加上一对大括号,如果是数组则首尾加上一对中括号。在处理数组的时候还要考虑数组元素是pojo,数组,集合或其它等情况,当然pojo的属性对象,也得考虑它是否是一个基本数据类,pojo,数组或其它等情况。下边看看我的代码。
public class JSONArray{
@SuppressWarnings("unchecked")
public static String toJson(Collection collection) {
StringBuffer buffer = new StringBuffer();
buffer.append("[");
for (Object object : collection) {
if (object instanceof Collection) {
System.out.println(object.toString());
JsonArray.toJson((Collection) object);
} else {
if (object.getClass().isArray()) {
System.out.println(object.toString());
JsonArray.toJson((Object[]) object);
} else {
if (buffer.length() > 1)
buffer.append(",");
buffer.append(JsonObject.toJson(object));
}
}
}
buffer.append("]");
return buffer.toString();
}
@SuppressWarnings("unchecked")
public static String toJson(Object[] collection) {
StringBuffer buffer = new StringBuffer();
buffer.append("[");
for (Object object : collection) {
if (object.getClass().isArray()) {
System.out.println(object.toString());
JsonArray.toJson((Object[]) object);
} else {
if (object instanceof Collection) {
System.out.println(object.toString());
JsonArray.toJson((Object[]) object);
} else {
if (buffer.length() > 1)
buffer.append(",");
buffer.append(JsonObject.toJson(object));
}
}
}
buffer.append("]");
return buffer.toString();
}
}
看看上边 这段代码,是不是很多if else语句,试想一下我如果再加入一个HashMap的处理方法进来,我
是不是要 到上边 每一个 方法都要加上这个类型的判断处理呢?哪以后再加 呢 ??是不是很难维护了。
所以,这个地方我们就应该采用 职责链模式来完成这个处理。职责链模式会将不同类型的处理提出来单独放在各自不同的类里去处理。当你传入的数据类型时,它会依次在这些处理类里传递,直到找到该类型的处理类为止。
好 ,先定义一个接口。如下:

责任链接口
1
/**//*
2
* @(#)JSONChain.java
3
* createTime:Apr 21, 2008 9:08:24 PM
4
*/
5
package com.sam.jsontool.util;
6
/** *//**
7
* @author sam E-mail:ashan8888@163.com
8
* @version 1.0
9
*/
10
public interface JSONChain
{
11
void addChain(JSONChain chain);
12
String doChain(Object objects) throws JSONException;
13
JSONChain getChain();
14
}
15
16
17
这个例子我们需要把不同数据类型提出来做相应处理。简单的可以分为,纯 pojo对象的 处理,数组的处理,集合的处理:代码如下:

纯对象的处理
1
/**//*
2
* @(#)JSONObject.java
3
* createTime:Apr 22, 2008 11:08:27 AM
4
*/
5
package com.sam.jsontool.util;
6
7
import java.beans.BeanInfo;
8
import java.beans.IntrospectionException;
9
import java.beans.Introspector;
10
import java.beans.PropertyDescriptor;
11
import java.lang.reflect.InvocationTargetException;
12
import java.lang.reflect.Method;
13
14
/** *//**
15
* @author sam E-mail:ashan8888@163.com
16
* @version 1.0
17
*/
18
public class JSONObject implements JSONChain
{
19
20
public void addChain(JSONChain chain)
{
21
22
}
23
24
public String doChain(Object objects)
{
25
26
return toJson(objects);
27
}
28
29
public JSONChain getChain()
{
30
return null;
31
}
32
33
/** *//**
34
* This method handles a object to a jsonText
35
*
36
* @param object
37
* which it will be convert a json text;
38
* @return a json text
39
* @throws IllegalArgumentException
40
* @throws IllegalAccessException
41
* @throws InvocationTargetException
42
* @throws IntrospectionException
43
*/
44
@SuppressWarnings("unchecked")
45
public static String toJson(Object object)
{
46
if (null == object)
47
return "null";
48
if (object.getClass().getPackage().getName().equals("java.lang"))
49
return object.toString();
50
Object methodResult = null;
51
BeanInfo beanInfo = getBeanInfo(object);
52
PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
53
Method method = null;
54
StringBuffer buffer = new StringBuffer();
55
buffer.append("{");
56
for (PropertyDescriptor descriptor : descriptors)
{
57
method = descriptor.getReadMethod();
58
if (null != method)
{
59
methodResult = invokeMethod(object, method);
60
if (null == methodResult)
61
methodResult = "null";
62
if (buffer.indexOf(":") > 1)
63
buffer.append(",");
64
buffer.append("\"" + descriptor.getName() + "\":");
65
66
if (!methodResult.getClass().getPackage().getName().equals(
67
"java.lang"))
{
68
buffer.append(toJson(methodResult));
69
} else
{
70
buffer.append(quote( methodResult.toString() ));
71
}
72
}
73
}
74
buffer.append("}");
75
return buffer.toString();
76
}
77
78
/** *//**
79
* This method is return a BeanInfo object and it without Object class's
80
* infomation.
81
*
82
* @param object
83
* @return
84
*/
85
private static BeanInfo getBeanInfo(Object object)
{
86
BeanInfo beanInfo = null;
87
try
{
88
beanInfo = Introspector
89
.getBeanInfo(object.getClass(), Object.class);
90
} catch (IntrospectionException e)
{
91
e.printStackTrace();
92
}
93
return beanInfo;
94
}
95
96
/** *//**
97
* this method is called when you want invoke a method via ref
98
*
99
* @param object
100
* @param method
101
* @return if no method find "null" will be return.
102
*/
103
private static Object invokeMethod(Object object, Method method)
{
104
Object result = null;
105
try
{
106
result = method.invoke(object, new Object[0]);
107
} catch (IllegalArgumentException e)
{
108
e.printStackTrace();
109
} catch (IllegalAccessException e)
{
110
e.printStackTrace();
111
} catch (InvocationTargetException e)
{
112
e.printStackTrace();
113
}
114
return result;
115
}
116
117
public static String quote(String string)
{
118
if (string == null || string.length() == 0)
{
119
return "\"\"";
120
}
121
122
char b;
123
char c = 0;
124
int i;
125
int len = string.length();
126
StringBuffer sb = new StringBuffer(len + 4);
127
String t;
128
129
sb.append('"');
130
for (i = 0; i < len; i += 1)
{
131
b = c;
132
c = string.charAt(i);
133
switch (c)
{
134
case '\\':
135
case '"':
136
sb.append('\\');
137
sb.append(c);
138
break;
139
case '/':
140
if (b == '<')
{
141
sb.append('\\');
142
}
143
sb.append(c);
144
break;
145
case '\b':
146
sb.append("\\b");
147
break;
148
case '\t':
149
sb.append("\\t");
150
break;
151
case '\n':
152
sb.append("\\n");
153
break;
154
case '\f':
155
sb.append("\\f");
156
break;
157
case '\r':
158
sb.append("\\r");
159
break;
160
default:
161
if (c < ' ')
{
162
t = "000" + Integer.toHexString(c);
163
sb.append("\\u" + t.substring(t.length() - 4));
164
} else
{
165
sb.append(c);
166
}
167
}
168
}
169
sb.append('"');
170
return sb.toString();
171
}
172
173
}
174
利用反射,读出属性和对应方法,并按json的格式输出字符串,为了前台方便转换,这里注意了转义字符的处理。
2:处理集合类型:

集合类型的处理
1
/**//*
2
* @(#)JSONCollection.java
3
* createTime:Apr 22, 2008 7:31:54 PM
4
*/
5
package com.sam.jsontool.util;
6
7
import java.util.Collection;
8
import java.util.Iterator;
9
10
/** *//**
11
* This class is handles Collection Object to a jsonText
12
*
13
* @author sam E-mail:ashan8888@163.com
14
* @version 1.0
15
*/
16
public class JSONCollection implements JSONChain
{
17
18
private JSONChain nextChain;
19
20
public void addChain(JSONChain chain)
{
21
this.nextChain = chain;
22
}
23
24
@SuppressWarnings("unchecked")
25
public String doChain(Object objects) throws JSONException
{
26
if ((null != objects) && (objects instanceof Collection))
{
27
StringBuffer buffer = new StringBuffer();
28
Iterator iterator = ((Collection) objects).iterator();
29
if (null == iterator)
{
30
buffer.append("null");
31
return buffer.toString();
32
}
33
buffer.append("[");
34
while (iterator.hasNext())
{
35
if (buffer.length() > 1)
36
buffer.append(",");
37
buffer.append(JSONTool.toJSON(iterator.next()));
38
}
39
buffer.append("]");
40
return buffer.toString();
41
} else
{
42
if (nextChain != null)
43
return nextChain.doChain(objects);
44
else
45
throw new JSONException("处理对象null异常");
46
}
47
}
48
49
public JSONChain getChain()
{
50
return nextChain;
51
}
52
53
}
54
3:数组的处理:

数组的处理
1
/**//*
2
* @(#)JSONObject.java
3
* createTime:Apr 21, 2008 8:08:42 PM
4
*/
5
package com.sam.jsontool.util;
6
7
/** *//**
8
* @author sam E-mail:ashan8888@163.com
9
* @version 1.0
10
*/
11
public class JSONArray implements JSONChain
{
12
13
private JSONChain nextChain;
14
15
public void addChain(JSONChain chain)
{
16
nextChain = chain;
17
}
18
19
public JSONChain getChain()
{
20
return nextChain;
21
}
22
23
public String doChain(Object objects) throws JSONException
{
24
if ((null!=objects)&& (objects.getClass().isArray()))
{
25
StringBuffer buffer = new StringBuffer();
26
buffer.append("[");
27
for (Object obj : (Object[]) objects)
{
28
if (buffer.length() > 1)
29
buffer.append(",");
30
buffer.append(JSONTool.toJSON(obj));
31
}
32
buffer.append("]");
33
return buffer.toString();
34
} else
{
35
if(nextChain != null)
36
return nextChain.doChain(objects);
37
else throw new JSONException("处理对象null异常");
38
}
39
40
}
41
42
}
43
4: 责任链的 组装
1
/**//*
2
* @(#)JSONClient.java
3
* createTime:Apr 22, 2008 8:41:10 AM
4
*/
5
package com.sam.jsontool.util;
6
7
8
/** *//**
9
* @author sam E-mail:ashan8888@163.com
10
* @version 1.0
11
*/
12
public class JSONTool
{
13
14
private static JSONArray array ;
15
private static JSONCollection collection;
16
private static JSONObject obj;
17
static
{
18
array= new JSONArray();
19
collection = new JSONCollection();
20
obj = new JSONObject();
21
collection.addChain(array);
22
array.addChain(obj);
23
}
24
25
26
public static String toJSON(Object object)
{
27
String result = null;
28
try
{
29
result = collection.doChain(object);
30
} catch (JSONException e)
{
31
e.printStackTrace();
32
}
33
return result;
34
}
35
36
37
}
38
5:测认结果:

简单的单元测试
1
/**//*
2
* @(#)JSONArrayTest.java
3
* createTime:Apr 21, 2008 8:22:27 PM
4
*/
5
package com.sam.jsontool.utiltest;
6
7
import java.util.ArrayList;
8
import java.util.HashSet;
9
import java.util.List;
10
11
import com.sam.jsontool.util.JSONTool;
12
13
import junit.framework.TestCase;
14
15
/** *//**
16
* @author sam E-mail:ashan8888@163.com
17
* @version 1.0
18
*/
19
public class JSONArrayTest extends TestCase
{
20
21
/** *//**
22
* 测试一个简单的javabean。
23
* @throws Exception
24
*/
25
public void testSimpleJB() throws Exception
{
26
Person person = new Person();
27
person.setName("男");
28
person.setAge(28);
29
person.setSex(true);
30
System.out.println(JSONTool.toJSON(person));
31
}
32
/** *//**
33
* 测试一个简单的 数组。
34
* @throws Exception
35
*/
36
public void testSimpleArray() throws Exception
{
37
Object[] objects = new Object[10];
38
for(int i = 0;i<10;i++)
{
39
Person person = new Person();
40
person.setName("男");
41
person.setAge(28+i);
42
person.setSex(true);
43
objects[i] = person;
44
}
45
System.out.println(JSONTool.toJSON(objects));
46
}
47
/** *//**
48
* 测试一个简单的 list.
49
* @throws Exception
50
*/
51
@SuppressWarnings("unchecked")
52
public void testSimpleList() throws Exception
{
53
List list = new ArrayList();
54
for(int i = 0;i<10;i++)
{
55
Person person = new Person();
56
person.setName("男");
57
person.setAge(28+i);
58
person.setSex(true);
59
list.add(person);
60
}
61
System.out.println(JSONTool.toJSON(list));
62
}
63
/** *//**
64
* 测试一个复合的 list
65
* @throws Exception
66
*/
67
@SuppressWarnings("unchecked")
68
public void testcomList() throws Exception
{
69
Object[] objects = new Object[3];
70
for(int i = 0;i<2;i++)
{
71
Person person = new Person();
72
person.setName("男");
73
person.setAge(28+i);
74
person.setSex(true);
75
objects[i] = person;
76
}
77
List list = new ArrayList();
78
list.add(123);
79
for(int i = 1;i<5;i++)
{
80
Person person = new Person();
81
person.setName("男");
82
person.setAge(28+i);
83
person.setSex(true);
84
if (i==2)
{
85
list.add(objects);
86
}else list.add(person);
87
}
88
System.out.println(JSONTool.toJSON(list));
89
}
90
91
/** *//**
92
* 测试集合元素中某集合为空的情况
93
* @throws Exception
94
*/
95
public void testCollection() throws Exception
{
96
97
List list = new ArrayList();
98
list.add("sam\\tiger");
99
100
list.add(new HashSet());
101
Person person = new Person();
102
person.setName("男");
103
person.setAge(28);
104
person.setSex(true);
105
list.add(person);
106
System.out.println(list.toString());
107
System.out.println(JSONTool.toJSON(list));
108
}
109
}
110
呵呵,现在要是加入HashMap的类型处理 是不是很简单了,只要加入一个类就可以了