您的位置:首页 > 编程语言 > Java开发

研磨设计模式 之 代理模式(Proxy)1??跟着cc学设计系列

2014-01-15 11:48 676 查看

11.1 场景问题

11.1.1 访问多条数据

考虑这样一个实际应用:要一次性访问多条数据。

这个功能的背景是这样的;在一个HR(人力资源)应用项目中客户提出,当选择一个部门或是分公司的时候,要把这个部门或者分公司下的所有员工都显示出来,而且不要翻页,好方便他们进行业务处理。在显示全部员工的时候,只需要显示名称即可,但是也需要提供如下的功能:在必要的时候可以选择并查看某位员工的详细信息。

客户方是一个集团公司,有些部门或者分公司可能有好几百人,不让翻页,也就是要求一次性的获取这多条数据并展示出来。

该怎么样实现呢?

11.1.2 不用模式的解决方案

不就是要获取某个部门或者某个分公司下的所有员工的信息吗?直接使用sql语句从数据库中查询就可以得到,示意性的SQL大致如下:

String sql = "select * from 用户表,部门表 "
+"where 用户表.depId=部门表.depId "
+"and 部门表.depId like '"+用户选择查看的depId+"%'";
为了方便获取某个部门或者某个分公司下的所有员工的信息,设计部门编号的时候,是按照层级来进行编码的,比如:上一级部门的编码为“01”,那么本级的编码就是“0101”、“0102”……以此类推,下一级的编码就是“010101”、“010102”……。

这种设计方式,从设计上看虽然不够优雅,但是实用,像这种获取某个部门或者某个分公司下的所有员工的信息的功能,就不用递归去查找了,直接使用like,只要找到以该编号开头的所有部门就可以了。

示例涉及到的表有两个,一个是用户表,一个是部门表。两个表需要描述的字段都较多,尤其是用户表,多达好几十个,为了示例简洁,简化后简单的定义如下:

DROP TABLE TBL_USER CASCADE CONSTRAINTS ;
DROP TABLE TBL_DEP CASCADE CONSTRAINTS ;

CREATE TABLE TBL_DEP (
DEPID VARCHAR2(20) PRIMARY KEY,
NAME VARCHAR2(20)
);
CREATE TABLE TBL_USER (
USERID VARCHAR2(20) PRIMARY KEY,
NAME VARCHAR2(20) ,
DEPID VARCHAR2(20) ,
SEX VARCHAR2(10) ,
CONSTRAINT TBL_USER_FK FOREIGN KEY(DEPID)
REFERENCES TBL_DEP(DEPID)
);
全部采用大写,是基于Oracle开发的习惯。再来增加点测试数据,SQL如下:

INSERT INTO TBL_DEP VALUES('01','总公司');
INSERT INTO TBL_DEP VALUES('0101','一分公司');
INSERT INTO TBL_DEP VALUES('0102','二分公司');
INSERT INTO TBL_DEP VALUES('010101','开发部');
INSERT INTO TBL_DEP VALUES('010102','测试部');
INSERT INTO TBL_DEP VALUES('010201','开发部');
INSERT INTO TBL_DEP VALUES('010202','客服部');
INSERT INTO TBL_USER VALUES('user0001','张三1','010101','男');
INSERT INTO TBL_USER VALUES('user0002','张三2','010101','男');
INSERT INTO TBL_USER VALUES('user0003','张三3','010102','男');
INSERT INTO TBL_USER VALUES('user0004','张三4','010201','男');
INSERT INTO TBL_USER VALUES('user0005','张三5','010201','男');
INSERT INTO TBL_USER VALUES('user0006','张三6','010202','男');
COMMIT;
准备好了表结构和测试数据,下面来看看具体的实现示例,为了示例的简洁,直接使用JDBC来完成。

(1)先来定义描述用户数据的对象,示例代码如下:

/**
* 描述用户数据的对象
*/
public class UserModel {
/**
* 用户编号
*/
private String userId;
/**
* 用户姓名
*/
private String name;
/**
* 部门编号
*/
private String depId;
/**
* 性别
*/
private String sex;

public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDepId() {
return depId;
}
public void setDepId(String depId) {
this.depId = depId;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String toString(){
return "userId="+userId+",name="+name+",depId="
+depId+",sex="+sex+"\n";
}
}

(2)接下来使用JDBC来实现要求的功能,示例代码如下:

/**
* 实现示例要求的功能
*/
public class UserManager {
/**
* 根据部门编号来获取该部门下的所有人员
* @param depId 部门编号
* @return 该部门下的所有人员
*/
public Collection<UserModel> getUserByDepId(
String depId)throws Exception{
Collection<UserModel> col = new ArrayList<UserModel>();
Connection conn = null;
try{
conn = this.getConnection();
String sql = "select * from tbl_user u,tbl_dep d "
+"where u.depId=d.depId and d.depId like ?";

PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, depId+"%");

ResultSet rs = pstmt.executeQuery();
while(rs.next()){
UserModel um = new UserModel();
um.setUserId(rs.getString("userId"));
um.setName(rs.getString("name"));
um.setDepId(rs.getString("depId"));
um.setSex(rs.getString("sex"));

col.add(um);
}
rs.close();
pstmt.close();
}finally{
conn.close();
}
return col;
}
/**
* 获取与数据库的连接
* @return 数据库连接
*/
private Connection getConnection() throws Exception {
Class.forName("你用的数据库对应的JDBC驱动类");
return DriverManager.getConnection(
"连接数据库的URL", "用户名", "密码");
}
}

(3)写个客户端来测试看看,是否能满足功能要求,示例代码如下:

public class Client {
public static void main(String[] args) throws Exception{
UserManager userManager = new UserManager();
Collection<UserModel> col =
userManager.getUserByDepId("0101");
System.out.println(col);
}
}

运行结果如下:

[userId=user0001,name=张三1,depId=010101,sex=男
, userId=user0002,name=张三2,depId=010101,sex=男
, userId=user0003,name=张三3,depId=010102,sex=男
]

你还可以修改getUserByDepId的参数,试试传递不同的参数,然后再看看输出的值,看看是否正确的实现了要求的功能。

11.1.3 有何问题

上面的实现看起来很简单,功能也正确,但是蕴含一个较大的问题,那就是:当一次性访问的数据条数过多,而且每条描述的数据量又很大的话,那会消耗较多的内存。

前面也说了,对于用户表,事实上是有很多字段的,不仅仅是示例的那么几个,再加上不使用翻页,一次性访问的数据就可能会有很多条。如果一次性需要访问的数据较多的话,内存开销会比较大。

但是从客户使用角度来说,有很大的随机性,客户既可能访问每一条数据,也可能一条都不访问。也就是说,一次性访问很多条数据,消耗了大量内存,但是很可能是浪费掉了,客户根本就不会去访问那么多数据,对于每条数据,客户只需要看看姓名而已。

那么该怎么实现,才能既把多条用户数据的姓名显示出来,而又能节省内存空间,当然还要实现在客户想要看到更多数据的时候,能正确访问到数据呢?

---------------------------------------------------------------------------

私塾在线学习网原创内容 跟着cc学设计系列 之 研磨设计模式

研磨设计讨论群【252780326】

原创内容,转载请注明出处【http://sishuok.com/forum/blogPost/list/5261.html

---------------------------------------------------------------------------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java