装饰模式和代理模式是GoF23种设计模式中的一部份。关于这两种模式的具体定义我不再赘述,网上有很多这方面的资料。我想说的是这两种模式的共通之处。这两种模式都可以用来给已存在的类的方法增加前、后置的代码。
使用装饰模式去扩充原有类的功能时,要求被扩充的类必须继承自一个接口,该接口定义了该类的行为,然后用一个新的装饰类实现这个接口,并将被扩充类的对象定义为一个成员变量,然后在重写接口方法时,调用被扩展类对象的相应方法,并在这个方法调用语句的前后加上部分需要添加的代码。
使用动态代理模式时,同样需要这样一个接口,切代理类也要实现这个接口,JDK1.3以后的版本为我们提供了一个动态代理很好的实现,具体代码如下:
package quickweb.db;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**************************************************
* NAME : DBSC.java
* HISTORY
* 2007-08-15 shanc 创建文件
* 注意:这个类是DBManager的代理类,用于在调用DB的DML方法时,加入前后置的
commit,rollback操作
* 注意:这个类是为了解决webcs中的不能自动提交的问题,但是由于这个问题产生的
根本原因是数据库设计的
* 不完善,无法用程序来解决这个问题,所以这种方式完全是为了学习
Proxy模式来做的。没什么实际意义
*************************************************/
public class DBSC implements InvocationHandler{
//需要被代理的类的实例
private DBManage db = null;
//定义需要代理的方法名的前缀,这里是DML方法
private static final String[] DMLMethodNames =
{"insert","update","del"};
public DBSupport bind(DBManage db){//创建一个代理类对象
this.db = db;
DBSupport proxyDb = (DBSupport) Proxy.newProxyInstance(//固定
写法
db.getClass().getClassLoader(),
db.getClass().getInterfaces(),
this);
return proxyDb;
}
/**
* 这个方法是接口定义的方法,必须实现
*/
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
Object obj = null;
if(this.isDMLMethod(method)){//是需要代理的方法
db.setAutoCommit(false);//附加操作
try{
obj = method.invoke(db, args);//调用真正的DB
方法
db.commit();//附加操作
}catch(Exception e){
db.rollback();//附加操作
}
}else{
obj = method.invoke(db, args);//不是需要代理的方法
}
return obj;
}
private boolean isDMLMethod(Method method){
for(int i = 0;i<DMLMethodNames.length;i++){//循环判断,看
method的名字是否符合DMLMethodNames中定义的
String DMLMethodName = DMLMethodNames[i];
String methodName = method.getName();
if(methodName != null && !"".equals(methodName) &&
methodName.startsWith(DMLMethodName))
return true;
}
return false;
}
}