java设计模式之代理模式

来源:互联网 发布:mac outlook windows 编辑:程序博客网 时间:2024/06/07 18:25

代理模式的主要作用是为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
代理模式的思想是为了提供额外的处理或者不同的操作而在实际对象与调用者之间插入一个代理对象。这些额外的操作通常需要与实际对象进行通信。
代理模式又可以分为静态代理和动态代理,下面分别用代码实现这两种代理模式。
静态代理:需要自己定义真实角色和代理角色,并且代理角色持有对真实角色的引用,同时两者实现了共同的接口,下面以明星和经纪人的关系用代码来实现静态代理。
两者共同实现的接口:

package com.zzit.staticproxy;/** * 静态代理模式 *  * @author yufu * */public interface Star {    /* 面谈 */    void confer();    /* 签合同 */    void signContract();    /* 唱歌 */    void sing();    /* 收款 */    void collect();}

真实角色:

package com.zzit.staticproxy;public class RealStar implements Star {    @Override    public void confer() {        System.out.println("真实角色面谈");    }    @Override    public void signContract() {        System.out.println("真实角色签合同");    }    @Override    public void sing() {        System.out.println("真实角色需要来做的事情************唱歌");    }    @Override    public void collect() {        System.out.println("真实角色收款");    }}

代理角色:

package com.zzit.staticproxy;/** * 代理类: * 需要持有被代理类的对象,一部分功能需要代理来做,核心功能还是真实角色来做 * @author yufu * */public class Proxy implements Star {    private Star star;    public Proxy(Star star) {        super();        this.star = star;    }    @Override    public void confer() {        System.out.println("代理面谈");    }    @Override    public void signContract() {        System.out.println("代理签合同");    }    @Override    public void sing() {        star.sing();    }    @Override    public void collect() {        System.out.println("代理收款");    }}

测试静态代理模式:

package com.zzit.staticproxy;/** * 注意代理类要持有被代理类的对象 * @author yufu * */public class Test {    public static void main(String[] args) {        Star s1=new RealStar();        Star s2=new Proxy(s1);        s2.confer();        s2.signContract();        s2.sing();        s2.collect();    }}

输出结果:

代理面谈代理签合同真实角色需要来做的事情************唱歌代理收款

静态代理模式实现起来比较简单,但是它有一个弊端,随着真实角色类的增多,每一真实角色类都需要为它添加一个代理角色来做那些公共的事情,无形中增加了很多不必要的重复,那么我们就要用到动态代理来实现代理模式。
使用动态代理需要牵扯到java中的两个类InvocationHandler(接口)和Proxy,它们都位于java.lang.reflect包下面,下面以房东出租房屋为例,来书写动态代理的代码实现。
房屋出租的接口:

package com.bjsxt.dynamicproxy;public interface Rent {    void rent();}

真实角色:

package com.bjsxt.dynamicproxy;public class Host implements Rent{    @Override    public void rent() {        System.out.println("真实角色出租房屋");    }}

代理类处理对象:

package com.bjsxt.dynamicproxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class ProxyInvocationHandler implements InvocationHandler {    private Rent rent;    public void setRent(Rent rent) {        this.rent = rent;    }    /**     * 生成代理类     */    public Object getProxy() {        // Proxy的newProxyInstance第一个参数为当前的类加载器,第二个参数为当前代理类的接口,第三个参数是当前ProxyInvocationHandler对象        // loader:定义代理类的类加载器        // interface:代理要实现的接口列表        // h:指派方法调用的调用处理程序        return Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(), this);    }    /**     * proxy:代理类对象     *      * method:代理类的调用处理程序的方法对象     */    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        seeHouse();        Object result = method.invoke(rent, args);        collectMoney();        return result;    }    private void seeHouse() {        System.out.println("中介带看房");    }    private void collectMoney() {        System.out.println("收中介费");    }}

测试代码:

package com.bjsxt.dynamicproxy;public class Client {    public static void main(String[] args) {        Host host=new Host();        ProxyInvocationHandler pih=new ProxyInvocationHandler();        pih.setRent(host);        Rent proxy=(Rent) pih.getProxy();        proxy.rent();    }}

输出结果:

中介带看房真实角色出租房屋收中介费