以2/8原则指导我们的底层框架设计 (转)
原创文章,转载请注明作者:Nomad,出处: www.jialing.net我想很多人都听说过“2/ 8 ” 原则,有人研究过,这世界上财富的80%集中在20%的人手里,而另外80%的人只拥用20%的财富。实际的商业中,我们应该更关注大客户,因为客户里20%的大客户,对我们贡献的利润可能会占到80%,这些都是有统计学基础的数据。
在应用软件的研发中同样遵守这个原则,我们写的20%底层代码将会起到80%的作用。做过Web项目的人应该都知道,大多数程序都是围绕增、删、改、条件查询等主题实现的,只是需求不同,具体的实现不同罢了。当项目重复性太高的时候,我们开始学习、使用框架技术,比如Hibernate就帮我们提取了很多对数据库操作的程序,目的也是减少程序员编写代码的数量与时间。而框架技术并不能包含我们工作的方方面面,我们依然需要在工作中不断总结、不断归纳,犹如Template设计模式,我们需要将重复的工作总结提炼出来,做成一个个模版,以此来不断简化我们的工作。所以我们需要以2/8原则指导开发设计,让更多的活交给框架去工作,让各种业务流做成模版类,做足底层的工作,将20%的底层代码发挥出80%贡献。
下面以我熟悉的平台框架举个模版的例子。在Hibernate框架下编写DAO层代码,我们需要从数据库中取出数据,以列表形式显示在页面上。这个例子将向你展示,只要做好底层工作,上层的业务逻辑就会变得非常简单(只有短短两行)。
1
//
CommonalityObject.java
2
3 // 用以装载数据并输出的Java Bean
4
5 public class CommonalityObject {
6 private String str1;
7 private String str2;
8 private String str3;
9 private String str4;
10 private String str5;
11 private String str6;
12 private String str7;
13 private String str8;
14
15
16
17 setters & getters
18
19}
20
21 // SQLTemplate.java
22
23 /** */ /**
24 * 报表中执行SQL查询的模版
25 * 以CommonalityObject来装载数据,运用反射机制加载返回List
26 *
27 * @author 李嘉陵
28 * @since 2006-7-14
29 */
30
31 public class SQLTemplate {
32
33 private static Log logger = LogFactory.getLog(SQLTemplate.class);
34
35 public List getQueryList(String sql, Session session) throws DAOException{
36 logger.info(sql);
37
38 try {
39 ResultSet reset = getReset(session,sql);
40 logger.info("r="+reset);
41 return reflectList(reset);
42 }
43 catch (Exception e1) {
44 // TODO Auto-generated catch block
45 e1.printStackTrace();
46 throw new DAOException(e1);
47 }
48 }
49
50 // 插入SQL获得相对应的数据集
51 public ResultSet getReset(Session s, String sql) throws Exception {
52
53 Connection conn = null;
54 Statement stat = null;
55 ResultSet reset = null;
56
57 //获得连接
58 conn = s.connection();
59
60 //装载数据块
61 stat = conn.createStatement();
62 //System.out.println("------运行的SQL语句--------"+sql);
63
64 //获得对应的数据集
65 reset = stat.executeQuery(sql);
66
67 return reset;
68 }
69
70 /** *//**
71 * 通过反射机制讲ResultSet中的数据以CommonalityObject形式载入List中,最后返回List
72 * @author 李嘉陵
73 * @since 2006-7-14
74 * @param reset SQL搜索出来的集合
75 * @return List<CommonalityObject>
76 * @throws Exception
77 */
78 public List reflectList(ResultSet reset) throws Exception{
79 List list = new ArrayList();
80
81 ResultSetMetaData meta = reset.getMetaData();
82
83 while(reset.next())
84 {
85 CommonalityObject co = new CommonalityObject();
86 String tmp="0";
87
88 for(int i=1;i<=meta.getColumnCount();i++) {
89 if (reset.getString(i) == null|| reset.getString(1).equals("") ){
90 tmp="0";
91 }
92 else{
93 tmp=reset.getString(i);
94 }
95
96 String method_name = "setStr"+i; //需要动态调用的函数名
97 Class cls=co.getClass(); //得到要在其中查找方法的类
98 Class partypes[] = new Class[]{String.class}; //函数调用的参数类型,这里为String。
99 Method mth=cls.getMethod(method_name, partypes); //得到方法
100 Object[] objs=new Object[]{tmp}; //生成函数要调用的数据,这里为tmp。
101 mth.invoke(co, objs); //调用得到的函数。
102 }
103
104 list.add(co);
105 }
106
107 return list;
108 }
109}
110
111 // 最终只要简单的两句就能完成报表的输出工作
112 public class OrderQryDAOImpl extends BaseDAOImpl implements OrderQryDAO {
113
114 public List getList(String cond) throws DAOException {
115
116 //SQL语句
117 String sqlStr = "" + cond;
118
119 return new SQLTemplate().getQueryList(sqlStr,getSession());
120
121 }
122}
2
3 // 用以装载数据并输出的Java Bean
4
5 public class CommonalityObject {
6 private String str1;
7 private String str2;
8 private String str3;
9 private String str4;
10 private String str5;
11 private String str6;
12 private String str7;
13 private String str8;
14
15
16
17 setters & getters
18
19}
20
21 // SQLTemplate.java
22
23 /** */ /**
24 * 报表中执行SQL查询的模版
25 * 以CommonalityObject来装载数据,运用反射机制加载返回List
26 *
27 * @author 李嘉陵
28 * @since 2006-7-14
29 */
30
31 public class SQLTemplate {
32
33 private static Log logger = LogFactory.getLog(SQLTemplate.class);
34
35 public List getQueryList(String sql, Session session) throws DAOException{
36 logger.info(sql);
37
38 try {
39 ResultSet reset = getReset(session,sql);
40 logger.info("r="+reset);
41 return reflectList(reset);
42 }
43 catch (Exception e1) {
44 // TODO Auto-generated catch block
45 e1.printStackTrace();
46 throw new DAOException(e1);
47 }
48 }
49
50 // 插入SQL获得相对应的数据集
51 public ResultSet getReset(Session s, String sql) throws Exception {
52
53 Connection conn = null;
54 Statement stat = null;
55 ResultSet reset = null;
56
57 //获得连接
58 conn = s.connection();
59
60 //装载数据块
61 stat = conn.createStatement();
62 //System.out.println("------运行的SQL语句--------"+sql);
63
64 //获得对应的数据集
65 reset = stat.executeQuery(sql);
66
67 return reset;
68 }
69
70 /** *//**
71 * 通过反射机制讲ResultSet中的数据以CommonalityObject形式载入List中,最后返回List
72 * @author 李嘉陵
73 * @since 2006-7-14
74 * @param reset SQL搜索出来的集合
75 * @return List<CommonalityObject>
76 * @throws Exception
77 */
78 public List reflectList(ResultSet reset) throws Exception{
79 List list = new ArrayList();
80
81 ResultSetMetaData meta = reset.getMetaData();
82
83 while(reset.next())
84 {
85 CommonalityObject co = new CommonalityObject();
86 String tmp="0";
87
88 for(int i=1;i<=meta.getColumnCount();i++) {
89 if (reset.getString(i) == null|| reset.getString(1).equals("") ){
90 tmp="0";
91 }
92 else{
93 tmp=reset.getString(i);
94 }
95
96 String method_name = "setStr"+i; //需要动态调用的函数名
97 Class cls=co.getClass(); //得到要在其中查找方法的类
98 Class partypes[] = new Class[]{String.class}; //函数调用的参数类型,这里为String。
99 Method mth=cls.getMethod(method_name, partypes); //得到方法
100 Object[] objs=new Object[]{tmp}; //生成函数要调用的数据,这里为tmp。
101 mth.invoke(co, objs); //调用得到的函数。
102 }
103
104 list.add(co);
105 }
106
107 return list;
108 }
109}
110
111 // 最终只要简单的两句就能完成报表的输出工作
112 public class OrderQryDAOImpl extends BaseDAOImpl implements OrderQryDAO {
113
114 public List getList(String cond) throws DAOException {
115
116 //SQL语句
117 String sqlStr = "" + cond;
118
119 return new SQLTemplate().getQueryList(sqlStr,getSession());
120
121 }
122}
看懂了吗?如果项目中我们需要完成几十个这样的报表输出,有了这样的底层代码结构,编写起来是不是很简单呢。