研磨设计模式之——代理模式

Posted huangyichun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了研磨设计模式之——代理模式相关的知识,希望对你有一定的参考价值。

案例:

  在一个项目中客户提出,选择一个部门或者分公司时,要把这个部门或者分公司的所有员工显示出来,而不要翻页。在现实员工时,只需要显示

名称即可,但是也需要提供查看员工详细信息。

  • 不用模式的解决方案

   用sql语句查询改分公司下的所有员工信息。我们使用jdbc模拟,底层数据库为mysql

  sql脚本如下:

 1 SET FOREIGN_KEY_CHECKS=0;
 2 
 3 -- ----------------------------
 4 -- Table structure for tbl_dep
 5 -- ----------------------------
 6 DROP TABLE IF EXISTS `tbl_dep`;
 7 CREATE TABLE `tbl_dep` (
 8   `depId` varchar(20) NOT NULL,
 9   `name` varchar(20) DEFAULT NULL,
10   PRIMARY KEY (`depId`)
11 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
12 
13 -- ----------------------------
14 -- Records of tbl_dep
15 -- ----------------------------
16 INSERT INTO `tbl_dep` VALUES (\'01\', \'总公司\');
17 INSERT INTO `tbl_dep` VALUES (\'0101\', \'一分公司\');
18 INSERT INTO `tbl_dep` VALUES (\'010101\', \'开发部\');
19 INSERT INTO `tbl_dep` VALUES (\'010102\', \'测试部\');
20 INSERT INTO `tbl_dep` VALUES (\'0102\', \'二分公司\');
21 INSERT INTO `tbl_dep` VALUES (\'010201\', \'开发部\');
22 INSERT INTO `tbl_dep` VALUES (\'010202\', \'测试部\');
23 
24 -- ----------------------------
25 -- Table structure for tbl_user
26 -- ----------------------------
27 DROP TABLE IF EXISTS `tbl_user`;
28 CREATE TABLE `tbl_user` (
29   `userId` varchar(20) NOT NULL,
30   `name` varchar(20) DEFAULT NULL,
31   `depId` varchar(20) NOT NULL,
32   `sex` varchar(10) DEFAULT NULL,
33   PRIMARY KEY (`userId`),
34   KEY `TBL_USER_FK` (`depId`),
35   CONSTRAINT `TBL_USER_FK` FOREIGN KEY (`depId`) REFERENCES `tbl_dep` (`depId`)
36 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
37 
38 -- ----------------------------
39 -- Records of tbl_user
40 -- ----------------------------
41 INSERT INTO `tbl_user` VALUES (\'user0001\', \'张三1\', \'010101\', \'\');
42 INSERT INTO `tbl_user` VALUES (\'user0002\', \'张三2\', \'010101\', \'\');
43 INSERT INTO `tbl_user` VALUES (\'user0003\', \'张三3\', \'010102\', \'\');
44 INSERT INTO `tbl_user` VALUES (\'user0004\', \'张三4\', \'010201\', \'\');
45 INSERT INTO `tbl_user` VALUES (\'user0005\', \'张三5\', \'010201\', \'\');
46 INSERT INTO `tbl_user` VALUES (\'user0006\', \'张三6\', \'010202\', \'\');
47 SET FOREIGN_KEY_CHECKS=1;

用户数据对象为:

 1 package com.huang;
 2 
 3 /**
 4  * Created by huangyichun on 2016/12/8.
 5  */
 6 public class UserModel {
 7 
 8     private String userId;
 9 
10     private String userName;
11     private String depId;
12     private String sex;
13 
14     public String getUserId() {
15         return userId;
16     }
17 
18     public void setUserId(String userId) {
19         this.userId = userId;
20     }
21 
22     public String getUserName() {
23         return userName;
24     }
25 
26     public void setUserName(String userName) {
27         this.userName = userName;
28     }
29 
30     public String getDepId() {
31         return depId;
32     }
33 
34     public void setDepId(String depId) {
35         this.depId = depId;
36     }
37 
38     public String getSex() {
39         return sex;
40     }
41 
42     public void setSex(String sex) {
43         this.sex = sex;
44     }
45 
46     @Override
47     public String toString() {
48         return "UserModel{" +
49                 "userId=\'" + userId + \'\\\'\' +
50                 ", userName=\'" + userName + \'\\\'\' +
51                 ", depId=\'" + depId + \'\\\'\' +
52                 ", sex=\'" + sex + \'\\\'\' +
53                 \'}\';
54     }
55 }

Jdbc实现功能

package com.huang;

import java.sql.*;
import java.util.ArrayList;
import java.util.Collection;

/**
 * Created by huangyichun on 2016/12/8.
 */
public class UserManager {

    public Collection<UserModel> getUserByDepId(String depId){

        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 preparedStatement = conn.prepareStatement(sql);
            preparedStatement.setString(1,depId + "%");

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

                col.add(um);
            }
            rs.close();
            preparedStatement.close();
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return col;
    }

    private Connection getConnection() throws Exception{
        Class.forName("com.mysql.jdbc.Driver");
        return DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root",//改成自己的账号密码
                "root");
    }
}

测试类:

package com.huang;

import java.util.Collection;

/**
 * Created by huangyichun on 2016/12/8.
 */
public class Client {

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

输出结果:

[UserModel{userId=\'user0001\', userName=\'张三1\', depId=\'010101\', sex=\'男\'},

UserModel{userId=\'user0002\', userName=\'张三2\', depId=\'010101\', sex=\'男\'},

UserModel{userId=\'user0003\', userName=\'张三3\', depId=\'010102\', sex=\'男\'}]

 

使用代理模式解决问题 

  1.代理模式的定义

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

  2. 代理模式解决思路

    代理模式引入一个Proxy对象来解决这个问题。刚开始只有用户编号和姓名的时候,不是一个完整的用户对象,而是一个代理对象。当需要访问

  完整的用户数据的时候,代理会从数据库中重新获取相应的数据,通常情况下是当客户需要访问除了用户编号和姓名之外的数据的时候,代理才会重新

  去获取数据。

  3.代理模式的结构和说明(图片是别人的

      

  4.代理模式的示例代码

  

package com.huang.proxy;

/**
 * 抽象的目标接口,定义具体的目标对象和代理公用的接口
 */
public interface Subject {
    /**
     * 示意方法:一个抽象的请求方法
     */
     void request();
}
package com.huang.proxy;

/**
 * 具体的目标对象,是真正被代理的对象
 */
public class RealSubject implements Subject {

    public void request() {
        //执行具体的功能处理
    }
}
package com.huang.proxy;


/**
 * 代理对象
 */
public class Proxy implements Subject {
    /**
     * 持有被代理的具体的目标对象
     */
    private RealSubject realSubject = null;

    /**
     * 构造方法,传入被代理的具体的目标对象
     * @param realSubject
     */
    public Proxy(RealSubject realSubject){
        this.realSubject = realSubject;
    }

    public void request() {
        //在转调具体的目标对象前,可以执行一些功能的处理

        //转调具体的目标对象的方法
        realSubject.request();

        //在转调具体的目标对象方法后,可以执行一些功能的处理
    }
}

下一篇讲述使用代理模式重写示例。

 

以上是关于研磨设计模式之——代理模式的主要内容,如果未能解决你的问题,请参考以下文章

java代码实现设计模式之代理模式

Java设计模式-代理模式之动态代理(附源代码分析)

Spring之代理模式

清华毕业大牛带你深入研磨并掌握23种设计模式,总计6.17G

创建型设计模式 之 单例模式

#yyds干货盘点# 设计模式之代理模式:动态代理