代理模式

转自:http://blog.csdn.net/luanlouis/article/details/24589193     

   代理模式上,基本上有Subject角色,RealSubject角色,Proxy角色。其中:Subject角色负责定义RealSubject和Proxy角色应该实现的接口;RealSubject角色用来真正完成业务服务功能;Proxy角色负责将自身的Request请求,调用realsubject 对应的request功能来实现业务功能,自己不真正做业务。

      

      上面的这幅代理结构图是典型的静态的代理模式:

       当在代码阶段规定这种代理关系,Proxy类通过编译器编译成class文件,当系统运行时,此class已经存在了。这种静态的代理模式固然在访问无法访问的资源,增强现有的接口业务功能方面有很大的优点,但是大量使用这种静态代理,会使我们系统内的类的规模增大,并且不易维护;并且由于Proxy和RealSubject的功能 本质上是相同的,Proxy只是起到了中介的作用,这种代理在系统中的存在,导致系统结构比较臃肿和松散。

       为了解决这个问题,就有了动态地创建Proxy的想法:在运行状态中,需要代理的地方,根据Subject 和RealSubject,动态地创建一个Proxy,用完之后,就会销毁,这样就可以避免了Proxy 角色的class在系统中冗杂的问题了。

下面以一个代理模式实例阐述这一问题:

   将车站的售票服务抽象出一个接口TicketService,包含问询,卖票,退票功能,车站类Station实现了TicketService接口,车票代售点StationProxy则实现了代理角色的功能,类图如下所示。

package com.foo.proxy;

/**
 * 售票服务接口实现类,车站
 * @author louluan
 */
public class Station implements TicketService {

    @Override
    public void sellTicket() {
        System.out.println("
	售票.....
");
    }

    @Override
    public void inquire() {
        System.out.println("
	问询。。。。
");
    }

    @Override
    public void withdraw() {
        System.out.println("
	退票......
");
    }

}
package com.foo.proxy;
/**
 * 售票服务接口 
 * @author louluan
 */
public interface TicketService {

    //售票
    public void sellTicket();
    
    //问询
    public void inquire();
    
    //退票
    public void withdraw();
    
}
package com.foo.proxy;

/**
 * 车票代售点
 * @author louluan
 *
 */
public class StationProxy implements TicketService {

    private Station station;

    public StationProxy(Station station){
        this.station = station;
    }
    
    @Override
    public void sellTicket() {

        // 1.做真正业务前,提示信息
        this.showAlertInfo("××××您正在使用车票代售点进行购票,每张票将会收取5元手续费!××××");
        // 2.调用真实业务逻辑
        station.sellTicket();
        // 3.后处理
        this.takeHandlingFee();
        this.showAlertInfo("××××欢迎您的光临,再见!××××
");

    }

    @Override
    public void inquire() {
        // 1做真正业务前,提示信息
        this.showAlertInfo("××××欢迎光临本代售点,问询服务不会收取任何费用,本问询信息仅供参考,具体信息以车站真实数据为准!××××");
        // 2.调用真实逻辑
        station.inquire();
        // 3。后处理
        this.showAlertInfo("××××欢迎您的光临,再见!××××
");
    }

    @Override
    public void withdraw() {
        // 1。真正业务前处理
        this.showAlertInfo("××××欢迎光临本代售点,退票除了扣除票额的20%外,本代理处额外加收2元手续费!××××");
        // 2.调用真正业务逻辑
        station.withdraw();
        // 3.后处理
        this.takeHandlingFee();

    }

    /*
     * 展示额外信息
     */
    private void showAlertInfo(String info) {
        System.out.println(info);
    }

    /*
     * 收取手续费
     */
    private void takeHandlingFee() {
        System.out.println("收取手续费,打印发票。。。。。
");
    }

}

代理模式可以起到保护的作用,也可以进行拓展,增强额外的功能。比如上面的例子有一个退票队列,存放乘客的退票车票。当接受订票请求时,先判退票队列里有没有,如果有,取出一张给乘客,无需再调用真实的订票接口;如果退票队列里没有,再调用真实订票接口。

原文地址:https://www.cnblogs.com/paulbai/p/5768365.html