代理模式

代理模式的定义:

Provide a surrogate or placeholder for another object to control access to it.(为其他对象提供一种代理以控制对这个对象的访问。)

代理模式通用类图

这里写图片描述


代理模式代码展示与分析

抽象主题类

package proxypattern;

public interface Subject {

    //定义一个该接口的功能方法
    public void request();
}

具体主题类

package proxypattern;

public class RealSubject implements Subject {

    @Override
    public void request() {
        // TODO Auto-generated method stub
        System.out.println("我是具体主题角色,也叫被委托或被代理对象");
    }

}

代理类

package proxypattern;

public class Proxy implements Subject {

    private Subject subject = null;

    //代理类的无参构造方法
    public Proxy() {
        //需要创建具体角色(或被代理角色)
        subject = new RealSubject();
    }
    //代理类的有参构造方法,把代理对象传进来,一般采用这种方法
    public Proxy(Subject subject) {
        this.subject = subject;
    }

    @Override
    public void request() {
        // 正常情况下代理类只实现被代理的具体方法this.subject.request()就可以了
        // 除了实现抽象主题所有的方法外 代理类一般也会给被代理类添加一些额外的功能
        // 在真实主题角色处理完毕前后做预处理和善后处理
        this.before();
        this.subject.request();
        this.after();
    }

    private void before() {
        System.out.println("代理类预处理");
    }

    private void after() {
        System.out.println("代理类善后处理");
    }

}

测试类

package proxypattern;

public class Test {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Subject sub = new RealSubject();
        Subject proxy = new Proxy(sub);
        proxy.request();
    }

}

测试结果:
代理类预处理
我是具体主题角色,也叫被委托或被代理对象
代理类善后处理


代理模式分析

  • 职责清晰
    真实角色实现他实际的业务逻辑不用关心其他非本职的事情,其他的由后期的代理完成。
  • 高扩展性
    具体角色随时都会变化,只要它实现了接口,代理类完全可以在不做任何修改的情况下使用。

    使用场景:只要是要完成核心事情,减轻负担,都可以,其他的复杂中间过程交给代理完成,最经典的场景是springAOP。

代理模式的扩展

  • 普通代理
  • 强制代理
  • 代理的个性化
  • 动态代理

    普通代理是我们必须知道代理的存在,即知道存在代理类这个类。普通代理的要求就是客户端只能访问代理角色,而不能访问真是角色。
    强制代理是调用者直接调用真是角色,不用关心代理存在,其代理的产生有真实角色决定。


普通代理模式

普通代理模式在通用类图上加以修改如下图
这里写图片描述

只需要修改下具体角色类和代理类即可,测试类直接使用代理测试。
修改后的代码如下
具体角色类:

package proxypattern;

public class RealSubject implements Subject {

    public RealSubject(Subject _subject) throws Exception {
        if(_subject == null) {
            throw new Exception("不能创建真实的角色");
        }
    }
    @Override
    public void request() {
        // TODO Auto-generated method stub
        System.out.println("我是具体主题角色,也叫被委托或被代理对象");
    }

}

代理类:

package proxypattern;

public class Proxy implements Subject {

    private Subject subject = null;

    //代理类的无参构造方法
    public Proxy() {
        try {
            subject = new RealSubject(this);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    @Override
    public void request() {
        // 正常情况下代理类只实现被代理的具体方法this.subject.request()就可以了
        // 除了实现抽象主题所有的方法外 代理类一般也会给被代理类添加一些额外的功能
        // 在真实主题角色处理完毕前后做预处理和善后处理
        this.before();
        this.subject.request();
        this.after();
    }

    private void before() {
        System.out.println("代理类预处理");
    }

    private void after() {
        System.out.println("代理类善后处理");
    }

}

测试类:

package proxypattern;

public class Test {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Subject proxy = new Proxy();
        proxy.request();
    }

}

测试结果
代理类预处理
我是具体主题角色,也叫被委托或被代理对象
代理类善后处理

结果和通用代码完全一致


强制代理模式

一般的思维都是通过代理找到真实角色,强制代理的思维是通过真实角色找到代理,否则不能访问。

修改下具体角色类和代理类,接口添加一行代码就可实现
修改后的代码如下
抽象主题接口

package proxypattern;

public interface Subject {

    //定义一个该接口的功能方法
    public void request();

    public Subject getProxy();
}

具体角色类

package proxypattern;

public class RealSubject implements Subject {

    private Subject proxy = null;

    public RealSubject() {}

    @Override
    public Subject getProxy() {
        this.proxy = new Proxy(this);
        return this.proxy;
    }
    @Override
    public void request() {
        // TODO Auto-generated method stub
        if(this.isProxy()) {
            System.out.println("我是具体主题角色,也叫被委托或被代理对象");
        } else {
            System.out.println("请使用指定代理访问");
        }

    }

    private boolean isProxy() {
        if(this.proxy == null) {
            return false;
        } else {
            return true;
        }
    }

}

代理类

package proxypattern;

public class Proxy implements Subject {

    private Subject subject = null;

    //代理类的无参构造方法
    public Proxy(Subject _subject) {
        this.subject = _subject;
    }

    @Override
    public void request() {
        // 正常情况下代理类只实现被代理的具体方法this.subject.request()就可以了
        // 除了实现抽象主题所有的方法外 代理类一般也会给被代理类添加一些额外的功能
        // 在真实主题角色处理完毕前后做预处理和善后处理
        this.before();
        this.subject.request();
        this.after();
    }

    private void before() {
        System.out.println("代理类预处理");
    }

    private void after() {
        System.out.println("代理类善后处理");
    }
    @Override
    public Subject getProxy() {
        // TODO Auto-generated method stub
        return this;
    }
}

测试类一 (对象直接访问)

package proxypattern;

public class Test {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Subject sub = new RealSubject();
        sub.request();
    }

}

输出结果
请使用指定代理访问

测试二 (通用测试类,将具体主题对象交给代理)

package proxypattern;

public class Test {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Subject sub = new RealSubject();
        Subject proxy = new Proxy(sub);
        proxy.request();
    }

}

测试结果
代理类预处理
请使用指定代理访问
代理类善后处理

测试三 (通过对象获取代理,再通过代理执行内容)

package proxypattern;

public class Test {

    public static void main(String[] args) {
        Subject sub = new RealSubject();
        Subject proxy = sub.getProxy();
        proxy.request();
    }

}

测试结果

代理类预处理
我是具体主题角色,也叫被委托或被代理对象
代理类善后处理

与通用类图结果一致


代理的个性化

通过接口对不同任务进行整合,在目标对象的方法的基础上作增强,这种增强的本质通常就是对目标的对象方法进行拦截和过滤。
代理类不仅仅是可以有自己的运算方法,通常情况下代理的职责并不一定单一,它可以组合其他的真实角色,也可以实现自己的职责。代理类可以为真实角色预处理消息、过滤消息、消息转发、事后处理消息等等。
个性化类图如下
这里写图片描述

添加接口IProxy

package proxypattern;

public interface IProxy {
    public void count();
}

代理类在通用代码上做如下修改

package proxypattern;

public class Proxy implements Subject,IProxy {

    private Subject subject = null;

    //代理类的无参构造方法
    public Proxy() {
        //需要创建具体角色(或被代理角色)
        subject = new RealSubject();
    }
    //代理类的有参构造方法,把代理对象传进来,一般采用这种方法
    public Proxy(Subject subject) {
        this.subject = subject;
    }

    @Override
    public void request() {
        // 正常情况下代理类只实现被代理的具体方法this.subject.request()就可以了
        // 除了实现抽象主题所有的方法外 代理类一般也会给被代理类添加一些额外的功能
        // 在真实主题角色处理完毕前后做预处理和善后处理
        this.before();
        this.subject.request();
        this.after();
    }

    private void before() {
        System.out.println("代理类预处理");
    }

    private void after() {
        System.out.println("代理类善后处理");
    }
    @Override
    public void count() {
        // TODO Auto-generated method stub
        System.out.println("其他接口计算功能");
    }

}

测试类在通用代码上做如下修改

package proxypattern;

public class Test {

    public static void main(String[] args) {
        Subject sub = new RealSubject();
        Proxy proxy = new Proxy(sub);
        proxy.request();
        proxy.count();
    }

}

输出结果为
代理类预处理
我是具体主题角色,也叫被委托或被代理对象
代理类善后处理
其他接口计算功能


动态代理模式太重要下一章节单独展示。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值