装饰者模式与动态代理

类的方法的增强的方式有很多,最初使用的继承,但继承的缺点是后期项目会产生很多的类,增加了项目的复杂度,于是,人们提出了组合,这点在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.........
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值