`
jendgh
  • 浏览: 16014 次
  • 性别: Icon_minigender_2
  • 来自: 济南
文章分类
社区版块
存档分类
最新评论

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

 
阅读更多

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

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

0
0
分享到:
评论
1 楼 spjich 2014-01-15  
驴头不对马嘴

相关推荐

    设计模式C++学习之代理模式(Proxy)

    设计模式C++学习之代理模式(Proxy)

    研磨设计模式(完整带书签).part2.pdf

    第11章 代理模式(Proxy) 第12章 观察者模式(Observer) 第13章 命令模式(Command) 第14章 迭代器模式(Iterator) 第15章 组合模式(Composite) 第16章 模板方法模式(Template Method) 第17章 策略模式...

    Android设计模式之代理模式(Proxy Pattern)

    Android设计模式之代理模式(Proxy Pattern)

    研磨设计模式(完整带书签).part1.pdf

    第11章 代理模式(Proxy) 第12章 观察者模式(Observer) 第13章 命令模式(Command) 第14章 迭代器模式(Iterator) 第15章 组合模式(Composite) 第16章 模板方法模式(Template Method) 第17章 策略模式...

    java 设计模式之代理模式(Proxy Pattern)实现代码及设计详解:动态代理模式、静态代理模式

    java 代理模式实现代码及设计详解:动态代理模式、静态代理模式

    设计模式之代理模式proxy

    为其他对象提供一个代理以控制对这个对象的访问。

    设计模式之代理模式proxy.zip

    代码仅供参考学习 。

    研磨设计模式-part2

    第11章 代理模式(Proxy) 第12章 观察者模式(Observer) 第13章 命令模式(Command) 第14章 迭代器模式(Iterator) 第15章 组合模式(Composite) 第16章 模板方法模式(Template Method) 第17章 策略模式...

    研磨设计模式.part1(共4个)

    第11章 代理模式(Proxy) 第12章 观察者模式(Observer) 第13章 命令模式(Command) 第14章 迭代器模式(Iterator) 第15章 组合模式(Composite) 第16章 模板方法模式(Template Method) 第17章 策略模式...

    研磨设计模式-part4

    第11章 代理模式(Proxy) 第12章 观察者模式(Observer) 第13章 命令模式(Command) 第14章 迭代器模式(Iterator) 第15章 组合模式(Composite) 第16章 模板方法模式(Template Method) 第17章 策略模式...

    研磨设计模式-part3

    第11章 代理模式(Proxy) 第12章 观察者模式(Observer) 第13章 命令模式(Command) 第14章 迭代器模式(Iterator) 第15章 组合模式(Composite) 第16章 模板方法模式(Template Method) 第17章 策略模式...

    结构型模式之代理模式(Proxy)

    2、代理模式(Proxy) 用意:为其它对象提供一种代理以控制对这个对象的访问

    设计模式之代理模式Proxy

    NULL 博文链接:https://wy649898543.iteye.com/blog/1431997

    研磨设计模式.part3(共4个)

    第11章 代理模式(Proxy) 第12章 观察者模式(Observer) 第13章 命令模式(Command) 第14章 迭代器模式(Iterator) 第15章 组合模式(Composite) 第16章 模板方法模式(Template Method) 第17章 策略模式...

    研磨设计模式.part2(共4个)

    第11章 代理模式(Proxy) 第12章 观察者模式(Observer) 第13章 命令模式(Command) 第14章 迭代器模式(Iterator) 第15章 组合模式(Composite) 第16章 模板方法模式(Template Method) 第17章 策略模式...

    研磨设计模式.part4(共4个)

    第11章 代理模式(Proxy) 第12章 观察者模式(Observer) 第13章 命令模式(Command) 第14章 迭代器模式(Iterator) 第15章 组合模式(Composite) 第16章 模板方法模式(Template Method) 第17章 策略模式...

    JAVA设计模式chm文档

    设计模式之Proxy(代理) 设计模式之Adapter(适配器) 设计模式之Composite(组合) 设计模式之Decorator(油漆工) 设计模式之Bridge 设计模式之Flyweight(享元) 行为模式: 设计模式之Template 设计模式之Memento(备忘机制...

    设计模式代码——c#

    12. 代理模式(Proxy Pattern) 行为型 13. 模板方法(Template Method) 14. 命令模式(Command Pattern) 15. 迭代器模式(Iterator Pattern) 16. 观察者模式(Observer Pattern) 17. 解释器模式(Interpreter ...

    设计模式可复用面向对象软件的基础.zip

    书名: 设计模式可复用面向对象软件的基础 英文原书名: Design Patterns:Elements of Reusable Object-Oriented software 作者: Erich Gamma 等 译者: 李英军 马晓星 蔡敏 刘建中 书号: 7-111-07575-7 页码: 254 定价...

    设计模式--可复用面向对象软件的基础

    4.7 PROXY(代理)——对象结构型模式 4.8 结构型模式的讨论 第五章 行为模式 5.1 CHAIN OF RESPONSIBIL ITY(职责链)——对象行为型模式 5.2 COMMAND(命令)——对象行为型模式 5.3 INTERPRETER(解释器)——类...

Global site tag (gtag.js) - Google Analytics