设计模式之——代理模式

8 篇文章 1 订阅
2 篇文章 0 订阅

静态代理

代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能.
这里使用到编程中的一个思想:不要随意去修改别人已经写好的代码或者方法,如果需要修改,可以通过代理的方式来扩展该方法

举个例子来说明代理的作用:假设我们想邀请一位明星,那么并不是直接联系明星,而是联系明星的经纪人,来达到同样的目的.明星就是一个目标对象,他只要负责活动中的节目,而其他琐碎的事情就交给他的代理人(经纪人)来解决.这就是代理思想在现实中的一个例子。

代理模式的关键点是:代理对象与目标对象.代理对象是对目标对象的扩展,并会调用目标对象

静态代理角色分析
抽象角色 : 一般使用接口或者抽象类来实现
真实角色 : 被代理的角色
代理角色 : 代理真实角色 ; 代理真实角色后 , 一般会做一些附属的操作 .
客户 : 使用代理角色来进行一些操作 .

代码实现:

写一个接口

public interface Singer {
    //定义一个唱歌的方法
    public void sing();

}

定义男歌手


public class MaleSinger implements Singer {
    @Override
    public void sing() {
        System.out.println("歌手开始唱歌");
    }


}

定义经纪人

public class Agent implements Singer {
    private Singer singer;

    public Agent(Singer singer) {
        this.singer = singer;
    }

    @Override
    public void sing() {
        System.out.println("节目组找过来!需要演出,谈好演出费用。。。。。");
        singer.sing();
        System.out.println("结算费用,下一次合作预约。。。。。。");
    }
}

Client . java 即客户


public class Client {
    public static void main(String[] args) {
        Singer singer = new zhouijelun();
        Singer maleSinger = new Agent(singer);
        maleSinger.sing();
    }
}

静态代理总结:
1.可以做到在不修改目标对象的功能前提下,对目标功能扩展.
2.缺点:
因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类,类太多.同时,一旦接口增加方法,目标对象与代理对象都要维护.
如何解决静态代理中的缺点呢?答案是可以使用动态代理方式

动态代理

  • 动态代理的角色和静态代理的一样 .
  • 动态代理的代理类是动态生成的 . 静态代理的代理类是我们写的
  • 动态代理分为两类 : 一类是基于接口动态代理 , 一类是基于类的动态代理
  • 基于接口的动态代理----JDK动态代理
  • 基于类的动态代理–cglib

动态代理就是当有大量的类需要执行一些共同代码时,我们自己写太麻烦,那能不能直接使用java代
码,自动生成一个类帮助我们批量的增强某些方法。

(1)JDK原生的动态代理

JDK动态代理是通过java.lang.reflect.Proxy类来实现的,我们可以调用Proxy类的newProxyInstance()方法来创建代理对象。对于使用业务接口的类,Spring默认会使用JDK动态代理来实现AOP。

代码实现:
创建UserDao接口,并编写添加方法和删除方法。

public interface UserDao {
    public void addUser();
    public void deleteUser();
}

创建userDao的实现类。

public class UserDaoImpl implements UserDao{
    @Override
    public void addUser() {
        System.out.println("添加用户");
    }

    @Override
    public void deleteUser() {
        System.out.println("删除用户");
    }
}

创建切面类,并定义模拟检查权限方法,和模拟记录日志方法。

public class MyAspect {
    public void check_Permissions(){
        System.out.println("模拟检查权限");
    }
    public void log(){
        System.out.println("模拟记录日志");
    }

}

创建代理类,该类需要实现InvocationHandler接口


/**
 * JDK代理类
 */
public class JdkProxy implements InvocationHandler {
    //声明目标类接口。
   private UserDao userDao;
   
   //创建代理方法
    public Object createProxy(UserDao o){
        this.userDao = o;
        //类加载器
        ClassLoader classLoader = JdkProxy.class.getClassLoader();
        //被代理对象实现的所有接口
        Class<?>[] interfaces = userDao.getClass().getInterfaces();
        //使用代理类,进行增强,返回的是代理后的对象
        return Proxy.newProxyInstance(classLoader,interfaces,this);
    }


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //声明切面
        MyAspect myAspect = new MyAspect();
        //前增强
        myAspect.check_Permissions();
        //在目标类上调用方法,并传入参数
        Object obj = method.invoke(userDao, args);
        //后增强
        myAspect.log();
        return obj;
    }
}


JDKProxy实现了InvocationHandler接口,并实现了接口中的invoke()方法,所有动态代理类所调用的方法都会讲给该方法处理。在创建的代理方法createProxy()中,使用了Proxy类的newProxyInstance()方法来创建代理对象。newProxyInstance()方法中包含3个参数,其中第一个参数是当前类的类加载器,第2个参数表示的是被代理对象实现的所有接口,第三个参数,this代表的就是代理类JdkProxy本身。在invoke()方法中,目标类方法执行的前后会分别执行切面类中的check_Permissions()方法和log()方法。

创建测试类:


public class JdkTest {
    public static void main(String[] args) {
        //创建代理对象
        JdkProxy jdkProxy = new JdkProxy();
        //创建目标对象
        UserDaoImpl userDao = new UserDaoImpl();
        //从代理对象中获取增强后的目标对象
        UserDao userDao1 = (UserDao) jdkProxy.createProxy(userDao);
        //执行方法
        userDao1.addUser();
        userDao1.deleteUser();
    }
}

执行结果:

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

200Ok。。

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值