【代理模式】

代理模式概述

为什么要有“代理”
生活中就有很多代理的例子,例如,我现在需要出国,但是我不愿意自己去办签证、预定机票和酒店(觉得麻烦 ,那么就可以找旅行社去帮我办,这时候旅行社就是代理,而我自己就是被代理了。

代理模式的定义
被代理者没有能力或者不愿意去完成某件事情,那么就需要找个人代替自己去完成这件事,这个人就是代理者, 所以代理模式包含了3个角色: 被代理角色 代理角色 抽象角色(协议)

代理模式UML类图
在这里插入图片描述

1、静态代理

这种代理方式需要代理对象和目标对象实现一样的接口。

优点:可以在不修改目标对象的前提下扩展目标对象的功能。

缺点:

  • 冗余。由于代理对象要实现与目标对象一致的接口,会产生过多的代理类。
  • 不易维护。一旦接口增加方法,目标对象与代理对象都要进行修改。

接口:

public interface Movie {
    void play();
}

被代理对象:

public class RealMovie implements Movie{
    @Override
    public void play() {
        System.out.println("正在播放《变形金刚5》");
    }
}

代理对象:

public class Cinema implements Movie{
    RealMovie realMovie;
    public Cinema(RealMovie realMovie) {
        this.realMovie = realMovie;
    }
    @Override
    public void play() {
        System.out.println("5月1日上新,超值");
        realMovie.play();
        System.out.println("电影结束!!!");
    }
}

测试:

public class Test {
    public static void main(String[] args) {
        //静态代理
       	RealMovie realMovie = new RealMovie();
        Cinema cinema = new Cinema(realMovie);
      	cinema.play();
      	/*
      	5月1日上新,超值
		正在播放《变形金刚5》
		电影结束!!!
      	*/
    }
}

2、动态代理

  • 概述 : 动态代理就是直接通过反射生成一个代理对象,代理对象所属的类是不需要存在的

  • 动态代理的获取:

    ​ jdk提供一个Proxy类可以直接给实现接口类的对象直接生成代理对象

动态代理相关api介绍

Java.lang.reflect.Proxy类可以直接生成一个代理对象

  • Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)生成一个代理对象
    • 参数1:ClassLoader loader 被代理对象的类加载器
    • 参数2:Class<?>[] interfaces 被代理对象的要实现的接口
    • 参数3:InvocationHandler h (接口)执行处理接口
    • 返回值: 代理对象
    • 前2个参数是为了帮助在jvm内部生成被代理对象的代理对象,第3个参数,用来监听代理对象调用方法,帮助我们调用方法
  • InvocationHandler中的Object invoke(Object proxy, Method method, Object[] args)方法:调用代理类的任何方法,此方法都会执行
    • 参数1:代理对象(慎用)
    • 参数2:当前执行的方法
    • 参数3:当前执行的方法运行时传递过来的参数
    • 返回值:当前方法执行的返回值

上面的代码用动态代码实现:

public class Test {
    public static void main(String[] args) {
        //静态代理
//        RealMovie realMovie = new RealMovie();
//        Cinema cinema = new Cinema(realMovie);
//        cinema.play();
        
        //动态代理
        RealMovie realMovie = new RealMovie();
        Movie movie = (Movie) Proxy.newProxyInstance(realMovie.getClass().getClassLoader(), realMovie.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("5月1日上新,超值");
                method.invoke(realMovie);
                System.out.println("电影结束!!!");
                return null;
            }
        });

        movie.play();
    }
}

案例:对Collection接口进行代理,以前的remove(Object obj)方法是删除集合中第一次出现的元素(比如集合中有多个“abc”,调用remove(“abc”)后只会删除一个元素)。代理后,要求在调用remove(Object obj)方法后,能够删除集合中所有匹配的元素。【动态代理】

public class H41 {
    public static void main(String[] args) {
        //集合
        Collection<String> list = new ArrayList<String>();
        Collections.addAll(list,"abc","auc","ahc","abc","abc","abc","akc","abc","abc")
        //动态代理
        Collection<String>  collection = (Collection<String>)Proxy.newProxyInstance(list.getClass().getClassLoader(), list.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Object res = method.invoke(list, args);
                if(method.getName().equals("remove")){
                    Iterator<String> it = list.iterator();
                    while (it.hasNext()){
                        String next = it.next();
                        if(next.equals(args[0])){
                            it.remove();
                        }
                    }
                }
                return res;
            }
        });

        collection.remove("abc");
        System.out.println(list);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值