Proxy 代理模式

Proxy 代理模式,第1张

定义

代理模式中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。

在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。

优缺点

优点:

  • 被代理类可以更加专注于主要功能的实现,在一定程度上降低了系统的耦合度。
  • 代理类可以提供额外的功能 。

缺点:

实现代理模式需要额外的工作,有些代理模式的实现非常复杂 。

使用场景
  • 在访问对象时附加一些 *** 作。
  • 控制对原始对象的访问,比如过滤器。
实现

分为静态代理和动态代理。

静态代理

在使用静态代理时,需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者继承相同的父类。

接口

public interface IMovie {
    void play();
}

实现类

public class Movie implements IMovie {
    @Override
    public void play() {
        System.out.println("观看电影中~~~~~~");
    }
}

代理类

public class MovieProxy implements IMovie {
    Movie movie;

    public MovieProxy(Movie movie) {
        this.movie = movie;
    }

    @Override
    public void play() {
        System.out.println("电影马上开始了!");
        movie.play();
        System.out.println("电影已结束,请有序退场!");
    }

}

这里也可以把增强代码封装成一个方法,再次解耦。

测试类

public class Main {
    public static void main(String[] args) {
        Movie movie = new Movie();
        IMovie movieProxy = new MovieProxy(movie);
        movieProxy.play();
    }
}

--------结果------
电影马上开始了!
观看电影中~~~~~~
电影已结束,请有序退场!

这里能看出,静态代理需要绑每个实现类都创建一个接口和一个代理类,如果实现类极多的情况下,是十分不方便的事。

所以产生了动态代理,利用反射,让我们的增强代码和实现类真正的解耦。

动态代理

分为JDK动态代理和CGLIB动态代理。这里使用JDK动态代理举例。

动态代理好处:

  • 代理类不需要再实现接口了(实现类依旧需要)。
  • 利用反射,动态在内存中构建代理对象。

JDK实现动态代理必须有实现 InvocationHandler 接口的处理类,如果需要写增强代码,则需重写 invoke 方法。

接口

public interface IMovie {
    void play();
}

实现类

public class Movie implements IMovie {
    @Override
    public void play() {
        System.out.println("观看电影中~~~~~~");
    }
}

代理类

这里使用了Object修饰对象,能让我们这个代理类,代理不同的实现类。同时利用了反射来获取实现类需要实现的方法,不再指定某个方法了。这些方式让我们的动态代理真正的实现了解耦。

public class MovieProxy {
    private Object target;

    public MovieProxy(Object target) {
        this.target = target;
    }

    public Object getProxyInstance() {
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("JDK代理开始~~");
                        System.out.println("电影马上开始了!");
                        // 反射机制调用目标函数的方法
                        Object ret = method.invoke(target, args);
                        System.out.println("电影已结束,请有序退场!");
                        System.out.println("JDK代理结束~~");
                        return ret;
                    }
                });
    }

}

测试类

public class Main {
    public static void main(String[] args) {
        Movie target = new Movie();
        IMovie proxyInstance = (IMovie) new MovieProxy(target).getProxyInstance();
        proxyInstance.play();
    }
}


--------结果------
JDK代理开始~~
电影马上开始了!
观看电影中~~~~~~
电影已结束,请有序退场!
JDK代理结束~~

PS:我们spring框架最重要之一的功能AOP就是使用了动态代理。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://www.outofmemory.cn/langs/729431.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-27
下一篇 2022-04-27

发表评论

登录后才能评论

评论列表(0条)

保存