java设计模式—代理模式

介绍

代理模式:由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。代理模式分为三种:静态代理、动态代理、Cglib代理

  • 优点
  1. 代理模式在客户端与目标对象之间起到一个中介作用和保护目标对象的作用;
  2. 代理对象可以扩展目标对象的功能;
  3. 代理模式能将客户端与目标对象分离,在一定程度上降低了系统的耦合度,增加了程序的可扩展性
  • 缺点
  1. 代理模式会造成系统设计中类的数量增加
  2. 在客户端和目标对象之间增加一个代理对象,会造成请求处理速度变慢;
  3. 增加了系统的复杂度

场景

出去旅游,拍照是必不可少的,尤其是自拍,单身狗自拍怎办?自拍杆,这里自拍杆可以看作是拍照的代理,摆好pos一按按钮完成拍照,以这个场景编写代理代码

静态代理

UML类图

在这里插入图片描述

实现方式

  1. 代理对象与被代理对象实现一个共同的接口
  2. 代理类聚合一个被代理对象
  3. 被代理对象交给代理对象,进行使用

代码

  • 接口
public interface IPhone {
    public void button();
}
  • 被代理类
public class Phone implements IPhone{
    @Override
    public void button() {
        System.out.println("单身狗开始自拍。。。");
    }
}

  • 代理类
public class SelfPhoneProxy implements IPhone{
    private IPhone iPhone;
    public SelfPhoneProxy(IPhone iPhone){
        this.iPhone = iPhone;
    }

    @Override
    public void button() {
        System.out.println("已经摆好pos...");
        iPhone.button();
        System.out.println("文明拍照,禁止虐狗...");
    }
    
	//测试类
	 public static void main(String[] args) {
        SelfPhoneProxy proxy = new SelfPhoneProxy(new Phone());
        proxy.button();
    }
}

在代理对象(目标对象)执行前后,可以植入一些想要实现功能:记录日志,安全校验,拦截等

动态代理

JDK代理

使用java 的反射机制,实现的代理模式

UML类图

在这里插入图片描述

实现方式

  1. 代理对象不需要继承接口,区别与静态代理,但是目标对象需要实现接口
  2. 代理对象使用反射机制生成,动态在内存中生成代理对象(也叫JDK、接口代理)

代码

  • 接口
public interface IPhone {
    public void button();
}
  • 被代理类
public class Phone implements IPhone{
    @Override
    public void button() {
        System.out.println("单身狗开始自拍。。。");
    }
}

  • 代理对象
public class SelfPhoneProxy {

    private Object target;
    public SelfPhoneProxy(Object target) {
        this.target = target;
    }

    /**
     * newProxyInstance
     * 第一个参数:目标对象类加载器
     * 第二个参数:目标对象实现的接口对象
     * 第三个参数:事件处理,执行目标对象时会触发的事件处理器方法,
     */
    public Object getProxyInstance() {
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(), (proxy,method,args) ->{
                        System.out.println("代理开始执行,请摆好pos...");
                        Object returnValue = method.invoke(target, args);
                        System.out.println("文明拍照,禁止虐狗...");
                        return returnValue;
                });
    }
}

Cglib代理

  1. 目标对象不需要实现接口,可以只是一个单纯的对象,可以使用目标对象的子类或者在内存中构建一个目标对象的子类实现动态代理,这就是Cglib代理,底层使用字节码处理框架ASM来转字节码并生成新类
  2. Cglib需要依赖 cglib 的包

UML类图

在这里插入图片描述

实现方式

  1. 代理类实现 MethodInterceptor 接口,通过 intecpet 方法实现对目标对象调用
  2. 目标对象不需要任何继承与实现,目标对象不能是 final/static 类型

代码

  • 被代理对象(目标对象)

  • 代理类
public class SelfPhoneCglibProxy implements MethodInterceptor {

    private Object target;
    public SelfPhoneCglibProxy(Object target){
        this.target = target;
    }

    public Object getProxInstance(){
        //创建Enhancer对象,类似于JDK动态代理的Proxy类
        Enhancer enhancer = new Enhancer();
        //设置父类
        enhancer.setSuperclass(target.getClass());
        //设置回调函数
        enhancer.setCallback(this);
        //这里的creat方法就是正式创建代理类(子类)
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("cglib动态代理。摆好pos...");
        Object invoke = method.invoke(target, args);
        System.out.println("拍照完,么么哒...");
        return invoke;
    }
}

  • 测试类
public static void main(String[] args) {
   //创建代理对象并将目标对象传递给代理独享
   SelfPhoneCglibProxy proxy = new SelfPhoneCglibProxy(new Phone());
   //通过代理获取目标对象
   Phone proxyObj = (Phone) proxy.getProxInstance();
   //调用目标对象方法,触发 intercept调用
   proxyObj.button();

}

总结

代理模式分为静态和动态代理,动态代理基于内存实现,动态区别在于目标类需不需要实现接口。代理运用非常广泛,在Spring AOP使用了代理,应用非常广泛。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值