第五章———代理模式
有两天没写博客了,主要是这两天比较疲惫;于是乎买了本书《牧羊少年奇幻之旅》一本《超越华尔街》一本;主要为了寻找迷失的方向和自己当初的理想;不忘初心,方得始终;今后更当修身养性,寻求内心的富足;好了今天我们来看看使用率相当高的代理模式;
看看定义:
Provide a surrogate or placeholder for another object to control access to it.(为其他对象提供
一种代理以控制对这个对象的访问。)
由定义可见;对其他对象提供一种代理,那就是有代理者和被代理者(委托类);就像总统发言人一样,他所说idea都代表总统的意思;他是总统的代理者;理清了原理我们就清晰多了后续,做什么我们就不会有那么多为什么。
首先我们看下静态代理:
假设有这么一个场景:我们都知道京东商城搞得是自营,所以国内服务和质量和速度做的很好;如果所有货源都从北京总部发货那肯定是做不到次日达或者当日达的;那么就要在各地设立分部仓储;这个是不是可以理解为代理模式;我寻找一个代理仓库负责这一片地方的货物供给:好了我们写了Demo;
定义一个统一仓库的接口
package com.ldl.proxytest;
public interface Warehouse {
public void receiveOrder();
public void findProduct();
public void packUpProduct();
public void sendOutProduct();
}
定义一个仓库的实现:
package com.ldl.proxytest;
public class WarehouseImpl implements Warehouse {
private String address;
public WarehouseImpl(String address) {
super();
this.address = address;
}
@Override
public void receiveOrder() {
System.out.println(address + "收到订单了");
}
@Override
public void findProduct() {
System.out.println(address + "在寻找订单");
}
@Override
public void packUpProduct() {
// TODO Auto-generated method stub
System.out.println(address + "在打包订单了");
}
@Override
public void sendOutProduct() {
// TODO Auto-generated method stub
System.out.println(address + "发出订单包裹了");
}
}
我们在搞一个代理类:
package com.ldl.proxytest;
public class WareHouseProxy implements Warehouse {
private Warehouse warehouse;
public WareHouseProxy(Warehouse warehouse) {
super();
this.warehouse = warehouse;
}
@Override
public void receiveOrder() {
// TODO Auto-generated method stub
this.warehouse.receiveOrder();
}
@Override
public void findProduct() {
// TODO Auto-generated method stub
this.warehouse.findProduct();
}
@Override
public void packUpProduct() {
// TODO Auto-generated method stub
this.warehouse.packUpProduct();
}
@Override
public void sendOutProduct() {
// TODO Auto-generated method stub
this.warehouse.sendOutProduct();
}
}
哈哈完事了我们搞个客户端测试一下呗:
package com.ldl.proxytest;
public class ProxyTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Warehouse wareHouse = new WarehouseImpl("深圳");
Warehouse wareHouseProxy = new WareHouseProxy(wareHouse);
wareHouseProxy.receiveOrder();
wareHouseProxy.findProduct();
wareHouseProxy.packUpProduct();
wareHouseProxy.sendOutProduct();
}
}
图片.png
欧了看到了吧效果还可以;我们用WareHouseProxy类代理WarehouseImpl;WarehouseImpl是个委托者;我委托你作为我的代理;是不是还挺简单?这就是静态代理模式;那么如果说京东像阿里一样一分为4独立运营该怎么办;难道我们要为4家分别实现一个接口分别搞一个代理吗?那么代理会不会显得冗余,代理除了调用方法不同其他是一样的;作为开发者看到重复代码就要想办法抽取;好了不卖关子了我们用动态代理解决这个问题:
动态代理即我们可以动态创建不同的代理类:
下面我们先改造一下Demo在解释:
package com.ldl.proxytest;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class WareHouseIH implements InvocationHandler {
// 被代理者
private Class cls;
// 代理谁(被代理的势力实例)
private Object obj;
public WareHouseIH(Object obj) {
super();
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(obj, args);
return result;
}}
测试一下:
package com.ldl.proxytest;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class ProxyTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Warehouse wareHouse = new WarehouseImpl("深圳");
InvocationHandler proxyHandler = new WareHouseIH(wareHouse);
// 我们动态创建一个代理对象
Warehouse proxy = (Warehouse) Proxy.newProxyInstance(wareHouse.getClass().getClassLoader(),
wareHouse.getClass().getInterfaces(), proxyHandler);
proxy.receiveOrder();
proxy.findProduct();
proxy.packUpProduct();
proxy.sendOutProduct();
// Warehouse wareHouseProxy = new WareHouseProxy(wareHouse);
// wareHouseProxy.receiveOrder();
// wareHouseProxy.findProduct();
// wareHouseProxy.packUpProduct();
// wareHouseProxy.sendOutProduct();
} }
InvocationHandler是JDK提供的动态代理接口,对被代理类的方法进行代理;其中invoke方法是接口InvocationHandler定义必须实现的,它完成对真实方法的调用。我
们来详细讲解一下InvocationHandler接口,动态代理是根据被代理的接口生成所有的方法,
也就是说给定一个接口,动态代理会宣称“我已经实现该接口下的所有方法了”,
所有被代理的方法都由InvocationHandler接管实际的处理任务
看一下通用类图:
图片.png
动态代理实现代理的职责,业务逻辑Subject实现相关的逻辑功能,两者之间没有必然的相互耦合的关系
注意 要实现动态代理的首要条件是:被代理类必须实现一个接口,回想一下前面的分
析吧。当然了,现在也有很多技术如CGLIB可以实现不需要接口也可以实现动态代理的方
式。这个我们知道就好,今天的任务是把代理搞明白;其实你清楚了原理;只要记住Proxy类即可;用时拿来即用;