设计模式学习之代理模式

来源:互联网 发布:大表妹是什么网络意思 编辑:程序博客网 时间:2024/06/06 07:00

什么是代理模式?

    代理模式通俗的讲就是用一个类去代理另一个类,那么我们为什么需要代理另一个类呢?通常我们在处理业务逻辑的过程中,可能会有一些附加动作需要做,例如记录操作记录等,这些内容本身并不是我们重要的业务流程,但又是不可缺少的,这个时候代理模式就派上了用场,这个就类似于我们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 stationsell railway ticket by railway stationsell 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.RailwayStationTicketOfficesell railway ticket by railway stationsell ticket from proxy







0 0
原创粉丝点击