设计模式之职责链 最近,在学习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的类型处理 是不是很简单了,只要加入一个类就可以了
|