一头扎进设计模式-代理模式

来源:互联网 发布:java统计字母,数字, 编辑:程序博客网 时间:2024/04/29 09:45

定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

用自己的话说:把真正运行的类封装到代理类里面,当实际调用时通过代理类去调用,代理类与真正运行的类实现同一套接口,代理类可以在真正操纵前对动作进行一些处理,适用为
远程代理:远程链接时,通过代理类隐藏网络获取等相关动作。
虚拟代理:使用代理代表开销大的对象或需要安全控制的对象
缓存代理:使用代理判断当前获取的内容是否已被缓存,是则调用缓存返回,否则调用真实的类进行获取。
保护代理:隐藏主体的某些动作,或屏蔽某些数据

java有提供相关api

简单的代理代码:
定义一个主体接口:

public interface Subject {    void request();}

定义一个真正的实体类:

public class RealSubject implements Subject {    /* (非 Javadoc)     * @see com.jjt.proxy.Subject#request()     */    @Override    public void request() {        System.out.println("真正做事的对象执行请求");    }}

定义一个代理:

public class Proxy implements Subject {    Subject realSubject = new RealSubject();    /* (非 Javadoc)     * @see com.jjt.proxy.Subject#request()     */    @Override    public void request() {        System.out.println("代理类调用实体类");        System.out.println("省略网络请求");        realSubject.request();    }}

测试:

    public static void main(String[] args){        Subject proxy = new Proxy();//新建一个代理去请求        proxy.request();    }

结果:

代理类调用实体类省略网络请求真正做事的对象执行请求

———————————————————————————————
动态代理,使用java api
代码:
定义一个人的接口:

/** * 代理与真正执行服务类继承的同个接口 * @author jiangjintai * */public interface PersonBean {     String getName();     String getGender();     String getInterests();     int getHotOrNotRating();     void setName(String name);     void setGender(String gender);     void setInterests(String interests);     void setHotOrNotRating(int rating);}

定义一个人的实现:

public class PersonBeanImpl implements PersonBean {    String name;    String gender;    String interests;    int rating;    int ratingCount = 0 ;    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public String getGender() {        return gender;    }    public void setGender(String gender) {        this.gender = gender;    }    public String getInterests() {        return interests;    }    public void setInterests(String interests) {        this.interests = interests;    }    public int getRating() {        return rating;    }    public void setRating(int rating) {        this.rating = rating;    }    public int getRatingCount() {        return ratingCount;    }    public void setRatingCount(int ratingCount) {        this.ratingCount = ratingCount;    }    /* (非 Javadoc)     * @see com.jjt.proxy.javaapi.PersonBean#getHotOrNotRating()     */    @Override    public int getHotOrNotRating() {        //         if(ratingCount==0) return 0;        return (rating/ratingCount);//返回平均分    }    /* (非 Javadoc)     * @see com.jjt.proxy.javaapi.PersonBean#setHotOrNotRating(int)     */    @Override    public void setHotOrNotRating(int rating) {//设置分数        this.rating+=rating;        ratingCount++;    }}

定义一个handle 用于控制动态代理类对实体类的操作
第一个handle 是不允许用户本人对自己设置分数

/** * InvocationHandler 是代理实例的调用处理程序 实现的接口 * 每个代理实例都具有一个关联的调用处理程序。对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的 invoke 方法 * @author jiangjintai * */public class OwnerInvocationHandler implements InvocationHandler {    PersonBean personBean;    /**     *      */    public OwnerInvocationHandler(PersonBean personBean) {        this.personBean=personBean;    }    /* (非 Javadoc)     * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])     */    @Override    public Object invoke(Object proxy, Method method, Object[] args)            throws Throwable {        if(method.getName().startsWith("get")){            return method.invoke(personBean, args);        }else if(method.getName().equals("setHotOrNotRating")){//在这里屏蔽设置分数方法            throw new IllegalAccessError();        }else if(method.getName().startsWith("set")){            return method.invoke(personBean, args);        }        return null;//别的方法不做处理    }}

第二个handle 是不允许别人对某个用户设置兴趣

public class NonOwnerlnvocationHandler implements InvocationHandler {    PersonBean personBean;    /**     *      */    public NonOwnerlnvocationHandler(PersonBean personBean) {        this.personBean=personBean;    }    /* (非 Javadoc)     * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])     */    @Override    public Object invoke(Object proxy, Method method, Object[] args)            throws Throwable {        if(method.getName().startsWith("get")){            return method.invoke(personBean, args);        }else if(method.getName().startsWith("setInterests")){//屏蔽方法            throw new IllegalAccessError();        }else if(method.getName().startsWith("set")){            return method.invoke(personBean, args);        }        return null;    }}

测试方法:

public  static void main(String[] args){        PersonBean personBean = new PersonBeanImpl();        personBean.setGender("男");        personBean.setHotOrNotRating(100);        personBean.setInterests("下棋");        personBean.setName("泰");        PersonBean ownerProxy = (PersonBean) Proxy.newProxyInstance(personBean.getClass().getClassLoader(), personBean.getClass().getInterfaces(),new OwnerInvocationHandler(personBean));        ownerProxy.setGender("女");        PersonBean nonOwnerProxy = (PersonBean)Proxy.newProxyInstance(personBean.getClass().getClassLoader(),personBean.getClass().getInterfaces(), new NonOwnerlnvocationHandler(personBean));        System.out.println(nonOwnerProxy.getGender());    }

测试:

public  static void main(String[] args){        PersonBean personBean = new PersonBeanImpl();        personBean.setGender("男");        personBean.setHotOrNotRating(100);        personBean.setInterests("下棋");        personBean.setName("泰");        PersonBean ownerProxy = (PersonBean) Proxy.newProxyInstance(personBean.getClass().getClassLoader(), personBean.getClass().getInterfaces(),new OwnerInvocationHandler(personBean));        ownerProxy.setGender("女");//      ownerProxy.setHotOrNotRating(10); 调用该方法抛出java.lang.IllegalAccessError异常        PersonBean nonOwnerProxy = (PersonBean)Proxy.newProxyInstance(personBean.getClass().getClassLoader(),personBean.getClass().getInterfaces(), new NonOwnerlnvocationHandler(personBean));        System.out.println(nonOwnerProxy.getGender());//      nonOwnerProxy.setInterests("吹牛");调用该方法抛出java.lang.IllegalAccessError异常    }
0 0