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