设计模式之代理模式

代理,一言以蔽之,就是第三方、中介的意思,比如卖家和买家之间不能直接交易,就需要一个中间人沟通两边以促成交易,和生活中的代理商、代理服务器之类其实都是同一种东西。

代理模式分为静态代理动态代理两种,先介绍比较简单的静态代理。

静态代理

静态代理可将买家的方法调用传给代理,在代理方法内部,实际调用卖家对象的相同方法,从而完成实际方法的调用。

通过两方面要求实现静态代理

  • 将卖家对象置于代理类中,如作为代理类的一个域
  • 代理类提供卖家的接口方法

动态代理

静态代理只能代理一个类的方法请求,那么当我们需要代理多个类的方法请求时,可用的办法有:

  • 在代理类中重新添加多个类对象的域,然后对外提供相应的接口
  • 新建多个代理类(这个太臃肿了)

动态代理用一种更加简洁、优雅的方式解决了上述问题,即根据代理方法请求动态地创建代理,并动态地处理代理方法调用

重要方法
  • Proxy静态newProxyInstance方法用来创建动态代理
    • loader表示类加载对象
    • interfaces表示代理对象实现的所有方法接口
    • h代表统一转发方法的调用处理器。

这里写图片描述

根据代码结果可知

  • loader只是提供一个类加载器,跟返回对象类型无关。
  • interfaces 决定返回对象的类型是Interfaces数组里面的任意一种类型,相当于返回的Object实现了interfaces中所有的方法接口,从方法的角度和多态的定义来看,Object是interface中任意class的对象。
  • InvocationHandler是动态代理执行调用转发的接口,要创建实现该接口的调用处理类,必须实现其抽象方法abstract Object invoke(Object proxy, Method method, Object[] args),利用反射机制使用Method.invoke()将请求转发给被代理对象(卖家)完成方法调用。

这里写图片描述

静态与动态代理对比

  • 静态代理:顾客把请求发给代理,代理的方法实现是在其内部创建实际服务者对象,然后调用实际服务者(卖家)对象的实际方法完成顾客请求。静态代理不仅可以有选择地提供实际服务者的部分接口方法,而且能在方法体内部调用实际服务者方法前后,添加属于自己的一些操作,这点类似于继承中的super调用。
    代理流程:这里写图片描述

  • 动态代理:顾客同样是把请求传给动态代理,但是在处理请求上,动态代理只是充当中间人或者中转站的角色,在动态代理中并不进行实际处理,只是将顾客请求(连同方法参数)转发给实际服务者,然后由实际服务者调用相应方法,完成请求。这其实有点通信中继站的意味了。
    代理流程:这里写图片描述

动态代理示例

//买家接口
public interface Customer {
    int order(String goods, Perchasing perchasing);
    boolean cancelOrder(int orderId, Perchasing perchasing);
}

//买家
public class Lucy implements Customer {


    public int order(String goods, Perchasing perchasing) {
        return perchasing.acceptOrder(goods);
    }


    public boolean cancelOrder(int orderId, Perchasing perchasing) {
        return perchasing.cancelOrder(orderId);
    }
}

//海外代购接口
public interface Perchasing {

    int acceptOrder(String goods);
    boolean cancelOrder(int orderId);
}

//实际代购者
public class WomanInUK implements Perchasing {

    private ArrayList<String> goodsList = new ArrayList<String>();

    public int acceptOrder(String goods) {
        goodsList.add(goods);
        int orderId = goodsList.indexOf(goods) + 1;
        System.out.println("Proxy : " + this.getClass().getName() + "\ngoods : "
                + goods + ", Order " + orderId);
        return orderId;
    }


    public boolean cancelOrder(int orderId) {
//      String cancelGoods = goodsList.get(orderId);
        goodsList.remove(orderId - 1);
        System.out.println("Proxy : "
        + this.getClass().getName() + "\nCacnel Order : " + orderId);
        return true;
    }

}

//动态代理类
public class PerchasingDynamicProxy implements InvocationHandler {

    private Object proxied;

    public PerchasingDynamicProxy(Object proxied){
        this.proxied = proxied;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("proxy : " + proxy.getClass() + "\nmethod :"
                + method + "\nargs :" + args);
        if (args != null) {
            for(Object arg : args)
                System.out.println("Method Parameter : " + arg);
        }
        System.out.println("-------------Invoke Dynamic Proxy-----------");
        //调用实际代理WomanInUK的对象方法
        return method.invoke(proxied, args);
    }

}

//海外代购测试
public class OverseasPerchasing {

    public static void main(String[] args) {
        Lucy lucy = new Lucy();
        WomanInUK realProxy = new WomanInUK();
        //调用真实代理
        lucy.order("MacBook Pro", realProxy);
        System.out.println("---------------Order----------------");
        //调用动态代理
        Perchasing perchasingProxy = (Perchasing) Proxy.newProxyInstance(
                Customer.class.getClassLoader(), new Class[]
                        {Perchasing.class, Customer.class}, new PerchasingDynamicProxy(realProxy));
        int order = lucy.order("SurfaceBook", perchasingProxy);
        //取消订单
        System.out.println("-----------Cacnel Orders-------------");
        if (lucy.cancelOrder(order, perchasingProxy)) {
            System.out.println("Canceling Orders Succeeds! ");
        }
    }

}

----------
//输出结果
Proxy : com.hwl.proxy.WomanInUK
goods : MacBook Pro, Order 1
---------------Order----------------
proxy : class com.sun.proxy.$Proxy0
method :public abstract int com.hwl.proxy.Perchasing.acceptOrder(java.lang.String)
args :[Ljava.lang.Object;@232204a1
Method Parameter : SurfaceBook
-------------Invoke Dynamic Proxy-----------
Proxy : com.hwl.proxy.WomanInUK
goods : SurfaceBook, Order 2
-----------Cacnel Orders-------------
proxy : class com.sun.proxy.$Proxy0
method :public abstract boolean com.hwl.proxy.Perchasing.cancelOrder(int)
args :[Ljava.lang.Object;@4aa298b7
Method Parameter : 2
-------------Invoke Dynamic Proxy-----------
Proxy : com.hwl.proxy.WomanInUK
Cacnel Order : 2
Canceling Orders Succeeds! 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值