OO模式-Proxy模式<一>静态代理
2015-11-03 11:23
260 查看
还依稀记得那个很经典的例子,王五喜欢一个女孩,但是过于害羞,让同伴李四代替自己去送花,最后女孩收到了话,但是猜想一下结果…………1、女孩很高兴,但是不知道到底是谁送的花;2、女孩很高兴李四送给自己花,并对李四有好感;3、女孩知道是王五托李四送给自己的话,心里甚是感激之情。当然咱们的重点并非是猜想最后的结果是什么,而是分析其实本来王五的事情却让李四去帮忙完成,没有直接和女孩交涉,这其实就是一个代理模式。
我们用一个简单的小实例来描述一下,到底何为代理?为什么要用代理?
先举一个小例子,比如我们只写一个简单的增删改查的小功能,需要创建两个类,一个接口类,一个实现类,然后最后是客户端调用,代码如下:
接口类:
到这里我们的小测试就完成了,但是看客户端方法,我们的用户直接调用了接口的实现类,这是万万不能的,如果我有大量的方式都来调用我们的实现类,这显然是不合理的,最好的情况还是避免直接交互的方式。现在不考虑这些,我们更换需求,要求在方法执行之前以及执行之后都进行提示,我们该如何去做?
看我们的实现类,其实就是在前后加两句输出代码来表示一下:
@Override
public void addUser(String userId, String userName) {
// 运行之前测试
System.out.println("start ==>addUser() userId ==>" + userId);
try {
// 实现
System.out.println("UserManagerImpl.addUser() userId ==>" + userId);
// 执行成功测试
System.out.println("success ==>addUser()");
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
// 执行失败测试
System.out.println("error ==>addUser()");
}
在实现中对每一个方法都增加同样的设置
客户端依旧如此调用,最后的效果图也只是前后多了两条输出语句。
代码执行完之后,我们思考一下,如果我有10个方法,我就得写10个同样的设置,最后终于写完了,但是老板突然又想改成别的需求了,比如只需要执行完提示就行,这样的话,就得一一的去每个方法中将不必要的提示去除掉……对于这种情况又该如何是好?所以我们这时候就可以考虑到我们的代理类模式
GoF定义代理模式:为其他对象提供一种代理以控制对这个对象的访问
针对上边的小例子,我们可以直接创建一个代理类来控制客户端对实现类的直接访问,代理类和其目标对象是一样的,所以两者实现共同的接口
新增的代理类:
/**
*
* @ClassName: UserManagerImplProxy
* @Description: 代理类,避免用户直接访问实现,和真实实体实现相同的接口
* @author: HuoYaJing
* @date:2015年11月2日 下午8:46:10
*/
public class UserManagerImplProxy implements UserManager {
private UserManager userManager;
// 创造一个构造方法,来传送目标
public UserManagerImplProxy(UserManager userManager) {
this.userManager = userManager;
}
@Override
public void addUser(String userId, String userName) {
try {
// 运行之前测试
System.out.println("start ==>addUser() userId ==>" + userId);
userManager.addUser(userId, userName);
// 执行成功测试
System.out.println("success ==>addUser()");
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
// 执行失败测试
System.out.println("error ==>addUser()");
}
}
我们客户端调用的时候,则避免了和实现类的直接访问,通过调用代理类来实现。
publicstatic void main(String[] args) {
// UserManageruserManager = new UserManagerImpl();
// 直接对代理类进行操作(代理类调用目标函数,目标函数调用实现类)
UserManageruserManager=new UserManagerImplProxy(new UserManagerImpl());
//
调用添加方法
userManager.addUser("0001","huohuo");
//
调用查找方法
userManager.findUser("0001");
}
最后的结果肯定也是和之前的结果是一样的,执行成功显示成功,执行失败,显示error提示。
这样通过代理类的出现,避免了用户直接访问目标函数,通过代理类的控制来进行访问。只是简单的加了一个代理类,这就是我们说的静态代理,静态代理存在什么问题呢?
需要建立大量的代理类,比如我增加方法需要代理类,删除方法也需要代理类……
重复的代码会出现在各个角落(和上一点是对应的)
由于静态代理的缺陷,所以动态代理才诞生,详情下篇博客-《OO模式-Proxy模式<二>动态代理》
我们用一个简单的小实例来描述一下,到底何为代理?为什么要用代理?
先举一个小例子,比如我们只写一个简单的增删改查的小功能,需要创建两个类,一个接口类,一个实现类,然后最后是客户端调用,代码如下:
接口类:
public interface UserManager { // 简单的增删改查方法 public void addUser(String userId, String userName); public void delUser(String userId); public void modifyUser(String userId, String userName); public String findUser(String userId); }实现类:
public class UserManagerImpl implements UserManager { @Override public void addUser(String userId, String userName) { // 实现 System.out.println("UserManagerImpl.addUser() userId ==>" + userId); } @Override public void delUser(String userId) { System.out.println("UserManagerImpl.delUser() userId ==>" + userId); } @Override public void modifyUser(String userId, String userName) { System.out.println("UserManagerImpl.modifyUser() userId ==>" + userId); } @Override public String findUser(String userId) { System.out.println("UserManagerImpl.findUser() userId ==>" + userId); return "huohuo"; } }最后客户端调用:
public static void main(String[] args) { UserManager userManager = new UserManagerImpl(); // 调用添加方法 userManager.addUser("0001", "huohuo"); // 调用查找方法 userManager.findUser("0001"); }最后的单元测试结果显示:
到这里我们的小测试就完成了,但是看客户端方法,我们的用户直接调用了接口的实现类,这是万万不能的,如果我有大量的方式都来调用我们的实现类,这显然是不合理的,最好的情况还是避免直接交互的方式。现在不考虑这些,我们更换需求,要求在方法执行之前以及执行之后都进行提示,我们该如何去做?
看我们的实现类,其实就是在前后加两句输出代码来表示一下:
@Override
public void addUser(String userId, String userName) {
// 运行之前测试
System.out.println("start ==>addUser() userId ==>" + userId);
try {
// 实现
System.out.println("UserManagerImpl.addUser() userId ==>" + userId);
// 执行成功测试
System.out.println("success ==>addUser()");
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
// 执行失败测试
System.out.println("error ==>addUser()");
}
在实现中对每一个方法都增加同样的设置
客户端依旧如此调用,最后的效果图也只是前后多了两条输出语句。
代码执行完之后,我们思考一下,如果我有10个方法,我就得写10个同样的设置,最后终于写完了,但是老板突然又想改成别的需求了,比如只需要执行完提示就行,这样的话,就得一一的去每个方法中将不必要的提示去除掉……对于这种情况又该如何是好?所以我们这时候就可以考虑到我们的代理类模式
GoF定义代理模式:为其他对象提供一种代理以控制对这个对象的访问
针对上边的小例子,我们可以直接创建一个代理类来控制客户端对实现类的直接访问,代理类和其目标对象是一样的,所以两者实现共同的接口
新增的代理类:
/**
*
* @ClassName: UserManagerImplProxy
* @Description: 代理类,避免用户直接访问实现,和真实实体实现相同的接口
* @author: HuoYaJing
* @date:2015年11月2日 下午8:46:10
*/
public class UserManagerImplProxy implements UserManager {
private UserManager userManager;
// 创造一个构造方法,来传送目标
public UserManagerImplProxy(UserManager userManager) {
this.userManager = userManager;
}
@Override
public void addUser(String userId, String userName) {
try {
// 运行之前测试
System.out.println("start ==>addUser() userId ==>" + userId);
userManager.addUser(userId, userName);
// 执行成功测试
System.out.println("success ==>addUser()");
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
// 执行失败测试
System.out.println("error ==>addUser()");
}
}
我们客户端调用的时候,则避免了和实现类的直接访问,通过调用代理类来实现。
publicstatic void main(String[] args) {
// UserManageruserManager = new UserManagerImpl();
// 直接对代理类进行操作(代理类调用目标函数,目标函数调用实现类)
UserManageruserManager=new UserManagerImplProxy(new UserManagerImpl());
//
调用添加方法
userManager.addUser("0001","huohuo");
//
调用查找方法
userManager.findUser("0001");
}
最后的结果肯定也是和之前的结果是一样的,执行成功显示成功,执行失败,显示error提示。
这样通过代理类的出现,避免了用户直接访问目标函数,通过代理类的控制来进行访问。只是简单的加了一个代理类,这就是我们说的静态代理,静态代理存在什么问题呢?
需要建立大量的代理类,比如我增加方法需要代理类,删除方法也需要代理类……
重复的代码会出现在各个角落(和上一点是对应的)
由于静态代理的缺陷,所以动态代理才诞生,详情下篇博客-《OO模式-Proxy模式<二>动态代理》
相关文章推荐
- 命令行窗口怎么切换根目录
- StringBuffer
- Shader 学习笔记 20151103
- 使用QtSingleApplication,实现应用只启动一个实例
- LeetCode--Contains Duplicate
- Android NDK环境配置
- 初学python小技巧【伯乐在线】
- 面试知识点总汇
- Collections.reverse 代码思考-超越昨天的自己系列(13)
- vs2015中github配置
- Deep Convolutional Network Cascade for Facial Point Detection阅读笔记
- 卧槽!这么简单MD
- Android开发环境配置中的名词解释
- 有源蜂鸣器与无源蜂鸣器有什么区别?
- Android Studio 第三方API 无效key问题解析
- JS人民币数字转换成大写形式
- PHP - 解决中文乱码问题
- cocos2d-x 2.2 study ------------------------ CCCallFunC家族
- java猜数字代码
- virtualbox中xp系统本地连接网络电缆被拔出