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

本文深入介绍了Java中的代理模式,包括静态代理和动态代理的概念及其实现方式。通过具体示例展示了如何利用代理模式来增强对象的功能,同时保持系统的灵活性和扩展性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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

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异常
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值