设计模式——代理模式

来源:互联网 发布:招聘网络平面设计师 编辑:程序博客网 时间:2024/05/21 08:58

代理对于我们来说再熟悉不过了,比如:代理商,代理律师。那么代理的到底是什么含义呢?代理就是受委托代表当事人进行某种活动。那么代理模式的核心作用是什么呢?就是通过代理,控制对象的访问。可以详细的控制访问某个或者是某类对象的方法,在调用这个方法前做前置处理,调用这个方法后做后置处理。
代理是在需要用比较通用和复杂的对象指针代替简单的指针的时候,使用代理模式。
下面是一些可以使用代理 模式常见情况:
1.远程代理为一个对象在不同的地址空间提供局部代表。
2.虚代理根据需要创建开销很大的对象,使得此对象只在需要时才会真正创建。
3.保护代理控制对原始对象的访问。
4.智能指引取代了简单的指针,它在访问对象时执行一些附加操作。
5.防火墙代理,保护目标,不让恶意用户接近。
代理又分为静态代理(静态定义代理类)和动态代理(动态生成代理类)两种。
动态代理相比较静态代理而言在抽象角色中(接口)声明的所有方法都被转移到调用处理器一个集中的方法中处理,这样的好处就是我们可以更加灵活和统一的处理众多的方法。
举个例子:假如说我在北京工作,接了一个上海的项目,但是由于太远我又不想去上海,怎么办呢?此时刚好我一个同学在上海上班,于是我就跟我的同学联系,让他帮我把这个项目谈过来。接项目肯定需要 面谈—>起草合同—>收首款—>做项目—>收尾款。除了完成项目的过程是由我本人执行之外,其他的都是由我同学来处理的,那么我同学所起的作用就是代理。
静态代理模式为
接项目过程

public interface Project {    String interview();    String drafContract();    String receiveFirst();    String doProjects ();    String endParagraph();}

本人自己

public class Mine implements Project {    @Override    public String interview() {        return "Mine--->interview";    }    @Override    public String drafContract() {        return "Mine--->drafContract";    }    @Override    public String receiveFirst() {        return "Mine--->receiveFirst";    }    @Override    public String doProjects() {        return "Mine--->doProjects";    }    @Override    public String endParagraph() {        return "Mine--->endParagraph";    }}

同学代理

public class ProxySchoolmate  implements Project{    private Mine mine;    public ProxySchoolmate(Mine mine) {        this.mine = mine;    }    @Override    public String interview() {        return "ProxySchoolmate--->interview";    }    @Override    public String drafContract() {        return "ProxySchoolmate--->drafContract";    }    @Override    public String receiveFirst() {        return "ProxySchoolmate--->receiveFirst";    }    @Override    public String doProjects() {        return  mine.doProjects();    }    @Override    public String endParagraph() {        return "ProxySchoolmate--->endParagraph";    }}

测试

  Mine mine = new Mine();  ProxySchoolmate proxySchoolmate = new ProxySchoolmate(mine);  System.out.println(proxySchoolmate.interview());  System.out.println(proxySchoolmate.drafContract());  System.out.println(proxySchoolmate.receiveFirst());  System.out.println(proxySchoolmate.doProjects());  System.out.println(proxySchoolmate.endParagraph());

运行效果
这里写图片描述
动态代理模式为
接项目过程和本人自己的内容完全相同,不同的是同学代理少了构造方法,多了一个动态代理机制的类
同学代理

public class ProxySchoolmate implements Project {    @Override    public String interview() {        return "ProxySchoolmate--->interview";    }    @Override    public String drafContract() {        return "ProxySchoolmate--->drafContract";    }    @Override    public String receiveFirst() {        return "ProxySchoolmate--->receiveFirst";    }    @Override    public String doProjects() {        return "ProxySchoolmate--->doProjects";    }    @Override    public String endParagraph() {        return "ProxySchoolmate--->endParagraph";    }}

动态代理机制类

public class ProjectHandler implements InvocationHandler {    Mine mine;    ProxySchoolmate proxySchoolmate = new ProxySchoolmate();    public ProjectHandler(Mine mine) {        this.mine = mine;    }    @Override    public Object invoke(Object proxy, Method method, Object[] objects) throws Throwable {        System.out.println(proxySchoolmate.interview());        System.out.println(proxySchoolmate.drafContract());        System.out.println(proxySchoolmate.receiveFirst());        if (method.getName().equals("doProjects")) {            proxy = method.invoke(mine, objects);            System.out.println(proxy.toString());        }        System.out.println(proxySchoolmate.endParagraph());        return proxy;    }}

测试

Mine mine = new Mine();ProjectHandler handler = new ProjectHandler(mine);Project project = (Project) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),new Class[]{Project.class},handler);project.doProjects();

运行效果与上面的运行效果相同。
下面来说一下动态代理机制
动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(接口)、另一个则是 Proxy(类),这一个接口和一个类是实现我们动态代理必不可少的。上面的使用也许大家已经看到了。如果我们要实现一个动态代理类首先必须要实现InvocationHandler这个接口,而且这个代理类实例需要关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转化为由InvocationHandler这个接口的 invoke 方法来进行调用。上面的ProjectHandler 这个类就是最好的证明。那么invoke(Object proxy, Method method, Object[] objects) throws Throwable 这个方法里面的三个参数各代表什么呢?
proxy:就是我们所代理的那个真实对象
method:就是我们所要调用真实对象的某个方法的Method对象
objects:就是调用真实对象某个方法时接受的参数
Proxy这个类的作用就是用来动态创建一个代理对象的类,它提供了许多的方法,但是我们用的最多的就是 newProxyInstance 这个方法,源码为

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException 

我们使用时为Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),new Class[]{Project.class},handler)这个方法里面也有三个参数,各代表什么呢?
loader:一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载
interfaces:一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了
h:一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上。
好了动态代理到此也就结束了,整个代理模式也就到这里了。

3 0
原创粉丝点击