在上一篇文章中<<代理模式之说说那些重复的代码事(1)>>我们介绍到关于那些重复代码的事情?如果做到上文中所提到的第三个方案.接下来我将用实际的代码来想大家展示如何通过添加静态代理来.
本文主要通过静态代理作为过渡,本文并没有完成上文提到的第三个方案.
整体代码主要分以下三部分
1原始代码
2面对新需求在原来的代码上进行更改.
3通过代理模式增加代理
普通代码演示:
系统的功能完成用户的增删改查:主要有以下的类和接口
接口:UserManager
/**
*用户管理
* @author Administrator
*
*/
public interfaceUserManager{
//添加用户
publicvoidaddUser(String userId,String userName);
//删除用户
publicvoiddelUser(String userId);
//查找用户
public StringfindUser(StringuserId,String userName);
//修改用户
publicvoidmodifyUser(String userId,String userName);
}
实现类:UserManagerImpl
publicclass UserManagerImpl implements UserManager {
//添加用户
publicvoid addUser(String userId, String userName) {
System.out.println("UserManagerImpl.addUser()userId-->"+userId);
}
//删除用户
publicvoid delUser(String userId) {
System.out.println("UserManagerImpl.delUser()userId-->"+userId);
}
//查找用户
publicString findUser(String userId, String userName) {
System.out.println("UserManagerImpl.findUser()userId-->"+userId);
returnuserName ;
}
//修改用户
publicvoid modifyUser(String userId, String userName) {
System.out.println("UserManagerImpl.modifyUser()userId-->"+userId);
}
}
客户端类:Client
publicclass Client {
publicstatic void main(String[] args){
//普通方式:真实的目标对象
//UserManageruserManager =new UserManagerImpl();
//静态代理模式:代理对象/
UserManageruserManager= new UserManagerImplProxy(new UserManagerImpl());
userManager.addUser("00001", "刘德华");
}
}
现在加入新的需求,为增删改差的每个方法加入日志维护功能.以
实现类:UserManagerImpl中的添加用户方法为例,如果在源代码上进行修改的话便是下面的代码:
实现类:UserManagerImpl
publicclass UserManagerImpl implements UserManager {
//添加用户
publicvoid 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(Exceptione){
e.printStackTrace();
//方法执行错误日志记录
//System.out.println("error--->addUser()");
}
}
//其他删改查方法都需要加上上面红色显示的语句.......
}
如此一来便需要在每一个方法上都加相同的代码语句.......
如果加入一个控制的话(例如日志控制),在原来的目标类添加非常麻烦,而且工作量大,也容易出错,如果要对此控制进行修改的话又将会是大量的工作,所以需要将此控制独立出来,通过AOP(Aspect Oriented Programming)的技术来实现.接下来便是文章的主角静态代理模式登场.整个代码的结构图如下:
使用静态代理模式:
加入一个代理类:此代理类实现UserManager接口
publicclass UserManagerImplProxy implements UserManager {
//获得目标方法
privateUserManager userManager;
publicUserManagerImplProxy(UserManager userManager){
this.userManager=userManager;
}
publicvoid addUser(String userId, String userName) {
try{
//开始日志记录
System.out.println("start---->addUser() userId-->"+userId);
//执行目标的方法
userManager.addUser(userId,userName);
//方法执行成功日志记录
System.out.println("success--->addUser()");
}catch(Exceptione){
e.printStackTrace();
//方法执行错误日志记录
System.out.println("error--->addUser()");
}
}
//其他方法代码类似故省略......
}
通过静态代理模式没有修改原来类的任何代码,只是增加了一个类,符合OCP(Open Closed Principle)原则原先的代码是直接和目标对象打交道.而现在通过代理类对目标对象进行一些控制(加入一些东西例如日志或者封装事务).
需要注意的是代理类和目标类的接口行为是一样的.都需要要实现同一个接口.(也就是说代理类和目标类的行为是一样的,不能更改参数,如果更改相关参数的话那就是另一个设计模式适配器模式).用户接触的只是代理,用户和代理之间可以通过工厂进行细节封装.
如果进一步思考的话问题又来了,通过静态代理虽然符合OCP原则,只是增加了一个类,但是如果面对大量的目标类需要增加代理的话,那就意味着需要数量相等的代理类.同时你也会看到重复的代码几乎遍布在各个角落里......我们上文中所提到的第三个方案并没有完整的进行实现.
想想的话也是很麻烦的一件很事情.如何解决这个问题呢?
答案请看接下来的文章:<<说说动态代理>>.