结构型模式之代理模式(Proxy 与 JDK动态代理)

代理模式,涉及到两个角色:代理者 委托者,即 ProxyDelegator,代理者不能真正做事,真正做事的只有委托者自己可以,代理者只是辅助作用而绝对不能(通常也没有能力)越俎代庖做委托者的事情,否则可能被代理的就是它自己了而不是它代理别人了

在程序设计中,代理模式被较多用途:

1.懒加载:某类实例化成本较高,为提高效率通常先快速返回一个代理对象,后续通过异步或在真正有需要的时候进行真正实例化。

2.权限检查:对某对象的访问需要满足一定的权限要求,可以通过代理者去检查权限,满足权限要求则交给对象处理,否则直接返回错误不再传递给对象。

3.日志处理:对某对象的方法进行日志记录等操作,可以通过代理者来做,通过扩展不同的代理者完成许多辅助工作,实际工作本身依然由委托者自己来做。

可以把代理者看作是对象访问的经纪人,一个对象可以有一个或多个经纪人,不同的经纪人拦截对象的访问进而可以进行不同的处理工作。


场景:周先生是一个大牌电影演员,很会拍电影,很多导演都想请他去拍电影,如果每个导演都打打电话问他可能会占用他很多时间,另外他的联系方式也不容易搞到,怎么办?

给周先生整个经纪人吧,他对周先生的日程安排、拍电影能力等全部清楚,而且他不是什么大牌,很多人都可以轻易找到他进而了解到周先生是否有空拍电影,甚至经纪人还会做些记录,比如哪些导演来找过他,找他有什么事等等,总之,除了拍电影本身他在别人看来和周先生就像一个人。


分析:经纪人和周先生在外界看来像同一个人,那么他们必需实现同一个接口,经纪人包揽周先生的日程安排,在真正拍电影的时候交由周先生去做,那么经济人势必要关联到周先生,很显然经纪人是一个轻量级的对象,可以很快响应外界的请求,甚至周先生一直不出面都不会影响把程序搞死,顶多是告诉请求者周先生很忙。


设计:

结构型模式之代理模式(Proxy 与 JDK动态代理)_第1张图片

示例代码:

interface MovieActor {
    void actMovie();
}
class MrZhou implements MovieActor {
    @Override
    public void actMovie() {
        System.out.println("周先生眼电影 ...");
    }
}
class ProxyActor implements MovieActor {
    private MovieActor movieActor;
    public ProxyActor(MovieActor movieActor) {
        this.movieActor = movieActor;
    }
    @Override
    public void actMovie() {
        System.out.println("经纪人先处理 ...");
        movieActor.actMovie();// 交给委托者来实际完成。
    }
}
public class Test {
    public static void main(String[] args) {
        MovieActor movieActor = new ProxyActor(new MrZhou());
        movieActor.actMovie();
    }
}

以上是代理模式的实现,下面是使用JDK动态代理实现:


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

interface MovieActor {
    void actMovie();
}
class MrZhou implements MovieActor {
    @Override
    public void actMovie() {
        System.out.println("周先生眼电影 ...");
    }
}
class ProxyActor implements InvocationHandler {
    private MrZhou mrZhou = new MrZhou();

    @Override
    // 参数里的 proxy 其实是 Proxy.newProxyInstance 产生的匿名代理对象,对此对象的使用容易引发循环调用进而导致栈内存溢出
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        String name = method.getName();
        System.out.println("看看找电影演员有什么事情:" + name);
        if (name.equals("actMovie")) {
            mrZhou.actMovie();
        }
        return null;//如果执行的方法有返回值,可以在这里返回
    }
}
public class Test {
    public static void main(String[] args) {
        MovieActor movieActor = (MovieActor) Proxy.newProxyInstance(
                MrZhou.class.getClassLoader(),
                MrZhou.class.getInterfaces(),
                new ProxyActor());
        movieActor.actMovie();
    }
}

你可能感兴趣的:(结构型模式之代理模式(Proxy 与 JDK动态代理))