设计模式学习之代理模式

什么是代理模式?

    代理模式通俗的讲就是用一个类去代理另一个类,那么我们为什么需要代理另一个类呢?通常我们在处理业务逻辑的过程中,可能会有一些附加动作需要做,例如记录操作记录等,这些内容本身并不是我们重要的业务流程,但又是不可缺少的,这个时候代理模式就派上了用场,这个就类似于我们spring中的aop。

代理模式的关键是什么?

    代理模式的关键是实现类与代理类的组合,如下图就是一个静态代理的结构:


静态代理实例分析

    我们可以考虑这么一个卖票的场景,假设一个人准备过年回家,需要买票,因此就需要有人卖票,下面我们定义一个卖票的接口:

/**
 * 售票处
 */
public interface TicketOffice {
    public void sellTicket();
}

    我们的火车站售票处作为合法的售票处,负责向乘客售票,因此我们实现一个火车票售票处:

/**
 * 火车站售票大厅
 */
public class RailwayStationTicketOffice implements TicketOffice {

    @Override
    public void sellTicket() {
        System.out.println("sell railway ticket by railway station");
    }
}
    这样就可以解决乘客买票的问题了,但是由于每年到了春运,买票回家的人太多了,火车站的容量有限,不可能接纳那么多乘客同事来买票,因此火车站想到了一个方案,在城市各个地方找一些自己的代理,让他们来替自己卖票,因此有了我们看到的火车票代售,在这里我们假设他们是通过先向火车站买入再卖出的模式,因此我们有了代理类:

/**
 * 火车票代理
 */
public class RailwayTicketProxy implements TicketOffice {
    private RailwayStationTicketOffice office = new RailwayStationTicketOffice();

    public void sellTicket() {
        System.out.println("buy railway ticket from railway station");
        office.sellTicket();
        System.out.println("sell railway ticket from proxy");
    }
}
    有了这些代理之后,乘客就不需要再去火车站排长队等待买票,而是在火车票代理就可以实现买火车票,然后我们实现client如下:

/**
 * 静态代理客户端
 */
public class StaticProxyClient {

    /**
     * 用户只关心买到票,对于火车票是如何买到的本身并不关心
     */
    public static void main(String[] args) {
        RailwayTicketProxy proxy = new RailwayTicketProxy();
        proxy.sellTicket();
    }

}
    我们的用户可以在代理那里同样买到火车票,而且根本不用关心这个火车票是怎么来的。运行结果如下:

buy railway ticket from railway station
sell railway ticket by railway station
sell railway ticket from proxy

    这种模式看样子很好,类似于此我们可以剥离开我们核心业务流程中的非核心操作,但是问题来了,如果有这么多类,我们就要搞这么多代理,对我们来说岂不是工作量加倍?而且对于记录操作记录,这些完全是同样的操作,我们是否能对他进行统一的配置呢?这就是动态代理的好处了。

动态代理实例分析

    同样是买票的场景,假设有人比较犹豫,我要买火车票呢?还是买飞机票呢?如果按照静态代理的模式,火车站找到了自己的代理,机场遇到了同样的情况,也找到了自己的代理,那么用户就不得不先去火车票代理询问火车票的价格,再去机场代理询问机票的价格,等问完决定回来买火车票的时候,发现火车票已经卖完了。用户花了时间、精力最后什么都没得到一定非常恼火,那么为什么我们不搞一个总的代理呢,在这里既可以询问火车票,也可以询问机票呢。因此我们动态代理实现如下:

/**
 * 总代理
 */
public class ProxyHandler implements InvocationHandler {

    //需要被代理的对象,火车票售票处?机票售票处?
    private Object target;

    //为我们的目标类生成动态代理
    public Object newProxyInstance(Object target) {
        this.target = target;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                                      target.getClass().getInterfaces(),
                                      this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("buy ticket from " + target.getClass().getName());
        Object result = method.invoke(target, args);
        System.out.println("sell ticket from proxy");
        return result;
    }
}

    如上所示我们生成了一个总的代理,可以由用户决定,我是要代理火车票售票处呢?还是代理机票售票处,最终决定如何买什么票。我们来看看动态代理的client端:

/**
 * 动态代理客户端
 */
public class DynamicProxyClient {

    public static void main(String[] args) {
        RailwayStationTicketOffice railwayOffice = new RailwayStationTicketOffice();
        ProxyHandler handler = new ProxyHandler();
        TicketOffice railwayOfficeProxy = (TicketOffice) handler.newProxyInstance(railwayOffice);
        railwayOfficeProxy.sellTicket();
    }

}
    最终用户决定我买火车票,因此我们通过代理火车票售票处,完成对用户售票。运行结果如下

buy ticket from DesignPattern.proxy.RailwayStationTicketOffice
sell railway ticket by railway station
sell ticket from proxy







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值