設計模式之職責鏈
最近,在學習ajax的時候,發(fā)現(xiàn)了一個前后臺傳輸數(shù)據(jù)的好東東:json,通過json字符串我們能很快的將java對象轉(zhuǎn)換成javascript對象,至于json具體是什么東西,可以上他的官方網(wǎng)站去查看一下。這里簡單的介紹一下: json用一對大括號來表示一個對象,并用冒號隔開屬性和值,用逗號分隔多個屬性。表示數(shù)組對象的時候json用一對中括號表示。如下:
1:json代碼來表示一個對象: {"name":"楊川","sex":"男","age":26}.
這就表示了一個人的對象。 它的屬性name = 楊川,性別=男 。年紀 =26歲。
2:json表示數(shù)組: [1,2,3,{"name":"sam","sex":"man"}].
這個就是一個數(shù)組, 其實熟悉javascript的人,都應該能看出來 json非常相似于javascript的直接量。比如數(shù)組直接量,對象直接量。
恩,到這里我簡單介紹一下我要做的事情。是這樣的,我們的javascript可以通過一個eval函數(shù),將json字串轉(zhuǎn)化成它自己的對象,比如上邊的那個對象我們要穿換成 我們的 javascript對象就可以這樣寫
jsonText = " {'name':'楊川','sex':'男','age':26}"
var person = eval('('+jsonText+')'); //得到一個javascrip對象
alert(person.name) //提示: 楊川。
所以,我們只要在java服務端將pojo生成一個個的json字符串,在前臺就可以 很簡單的轉(zhuǎn)換為js對象了。為前臺的數(shù)據(jù)使用提供了很大的方便 。
因此我嘗試寫了這么一個轉(zhuǎn)換工具包,結果,在編寫的時候,發(fā)現(xiàn)職責鏈模式到時很適合這個。就拿來用了。呵呵,當然我下邊的 代碼不一定是唯一的,完善的,如果各位看客有更好的 思路和方法。還請賜教啊。
好了,言歸正傳了。
我對職責鏈的理解是這樣的,在處理某些業(yè)務的時候,我們可能會判斷不同的情況去選擇做不同的業(yè)務處理,這樣就可能導致大量的if else語句組出來。導致程序的擴展維護相當困難,就比如我這里轉(zhuǎn)換json的這個例子,我的一個tojson(Object object)函數(shù)。他里邊就要判斷這樣一些情況,如果是一個pojo則返回的字符串首尾加上一對大括號,如果是數(shù)組則首尾加上一對中括號。在處理數(shù)組的時候還要考慮數(shù)組元素是pojo,數(shù)組,集合或其它等情況,當然pojo的屬性對象,也得考慮它是否是一個基本數(shù)據(jù)類,pojo,數(shù)組或其它等情況。下邊看看我的代碼。
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的處理方法進來,我
是不是要 到上邊 每一個 方法都要加上這個類型的判斷處理呢?哪以后再加 呢 ??是不是很難維護了。
所以,這個地方我們就應該采用 職責鏈模式來完成這個處理。職責鏈模式會將不同類型的處理提出來單獨放在各自不同的類里去處理。當你傳入的數(shù)據(jù)類型時,它會依次在這些處理類里傳遞,直到找到該類型的處理類為止。
好 ,先定義一個接口。如下:

責任鏈接口
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
這個例子我們需要把不同數(shù)據(jù)類型提出來做相應處理。簡單的可以分為,純 pojo對象的 處理,數(shù)組的處理,集合的處理:代碼如下:

純對象的處理
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的格式輸出字符串,為了前臺方便轉(zhuǎn)換,這里注意了轉(zhuǎn)義字符的處理。
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:數(shù)組的處理:

數(shù)組的處理
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
* 測試一個簡單的 數(shù)組。
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
呵呵,現(xiàn)在要是加入HashMap的類型處理 是不是很簡單了,只要加入一個類就可以了