类的方法的增强的方式有很多,最初使用的继承,但继承的缺点是后期项目会产生很多的类,增加了项目的复杂度,于是,人们提出了组合,这点在Go语言设计最突出,Go语言甚至去掉了类的继承,在java的设计模式的,类的增强的设计模式常见有装饰者模式和动态代理,本文阐述装饰者模式和动态代理模式的设计技巧.
装饰者模式
装饰者模式可以实现对一个类的方法的前后增强,为了更好的阐述该模式的原理,我从一个Service层的添加用户的方法addUser()展开
首先写一个接口UserService,中有一个addUser()方法
public interface UserService {
void addUser();
}
实现UserService
public class UserServiceImp implements UserService {
@Override
public void addUser() {
System.out.println("add user ........");
}
}
写一个装饰类,前置增强addUser() 方法,指定其构造方法,使得在创建类的时候,传入UserService,并保存在属性中,在重写的方法中调用
public class UserServiceBeforeDecorate implements UserService {
private UserService userService;
public UserServiceBeforeDecorate(UserService userService){
this.userService=userService;
}
@Override
public void addUser() {
//前置增强
System.out.println("before decorate..........");
userService.addUser();
}
}
写一个UserService的后置增强方法,与上面类似
public class UserServiceAfterDecorate implements UserService {
private UserService userService;
public UserServiceAfterDecorate(UserService userService){
this.userService=userService;
}
@Override
public void addUser() {
userService.addUser();
//后置增强
System.out.println("after decorate ..........");
}
}
写一个测试类
@Test
public void test3(){
UserServiceBeforeDecorate decorate = new UserServiceBeforeDecorate(new UserServiceAfterDecorate(new UserServiceImp()));
decorate.addUser();
}
这种写法是不是很熟悉,在java的IO中,就是这样设计的
// IO的使用
try {
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(new File("lhc.txt")));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
但也可以看到,在java的IO的API中,出现了众多的小类,增加了IO的复杂度,这也是装饰者模式中不可避免的缺点
动态代理
增强类的方法的另一种方式是使用动态代理,Spring框架的AOP也是基于此,我同样从一个Service层的添加用户的方法addUser()展开,看如何前后置增强
使用动态代理,需要写一个类实现InvocationHandler ,同样,指定其构造方法,在创建类的时候注入UserService ,并保存到属性中,值得关注的是重写的invoke的方法参数含义
其中method指的是被代理的对象的方法,args指的是被代理的对象的方法的参数,故使用反射执行该方法,并添加前后置增强
public class UserServiceInvocationHandler implements InvocationHandler {
private UserService userService;
public UserServiceInvocationHandler(UserService userService){
this.userService=userService;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//对UserService的每一方法的前后置增强
System.out.println("addUser before.........");
Object invoke = method.invoke(userService, args);
System.out.println("addUser after.........");
return invoke;
}
}
写一个测试,使用Prox的newProxyInstance方法,创建代理对象,需要传入三个参数
第一个:实现类的类加载器
第二个: 实现类所实现的所有接口
第三个就是上面写的实现InvocationHandler 的类
@Test
public void test6(){
UserService userServiceImp = new UserServiceImp();
UserService userService = (UserService)Proxy.newProxyInstance(userServiceImp.getClass().getClassLoader(), userServiceImp.getClass().getInterfaces(), new UserServiceInvocationHandler(userServiceImp));
userService.addUser();
}
调用器addUser方法,可看到控制台输出方法的前后置增强
addUser before.........
add user ........
addUser after.........