代理模式

代理模式

四月 09, 2019

什么是代理

这里的代理与我们生活中的中介其实差不多,就拿买房来说,由于现在炒房的人多,我们自己去买房很难,有些人就会找中介帮忙,给一些好处费,让后他拿了钱,就会帮我们获得购房资格。从这里可以看出来,代理的作用只是实现功能的增强,依旧依赖对象本身。

静态代理

静态代理是代理模式最原始的一种实现方式。每个代理都必须有一个接口实现类。我们有一个买房接口如下:

1
2
3
public interface BuyHouse {
void buy();
}

它有一个原始实现类,即自己去买房:

1
2
3
4
5
6
7
public class BuyHouseImpl implements BuyHouse {
@Override
public void buy() {
System.out.println("自己排队认筹");
System.out.println("付款签订合同");
}
}

但是现在问题来了,炒房的人太多了,我们自己根本买不到,这个时候我们只能花钱找中介帮我门获取买房的资格:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class BuyHouseProxy implements BuyHouse {
private BuyHouse base;

public BuyHouseProxy(BuyHouse base) {
this.base = base;
}

@Override
public void buy() {
System.out.println("中介收取好处费,帮你获取买房资格");
base.buy();
}
}

运行结果如下:

中介收取好处费,帮你获取买房资格
自己排队认筹
付款签订合同

这个时候,我们给中介一笔钱,获取资格,后面的认筹,交钱,签合同还是我们自己来。从这里可以看出来,前面为什么说代理模式只是功能的增强了。这也是符合开闭原则的。

动态代理

静态代理需要为每个代理写一个代理类,如果代理多了,就会非常麻烦。为了更优雅的实现代理,动态代理就产生了。

比如,我们买房找中介的时候,有2个中介,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class BuyHouseImplA implements BuyHouse {
@Override
public void buy() {
System.out.println("代理A收取5万茶水费");
System.out.println("自己排队认筹");
System.out.println("付款签订合同");
}
}

public class BuyHouseImplB implements BuyHouse {
@Override
public void buy() {
System.out.println("代理B收取3万茶水费");
System.out.println("自己排队认筹");
System.out.println("付款签订合同");
}
}

如果通过动态代理,我们就不需要分别为这两个中介写代理类了。只需要通过Proxy类的newProxyInstance()方法就可以动态生成代理。

1
2
3
4
5
6
7
8
9
10
11
public class DynamicBuyHouseTest {
public static void main(String[] args) {
BuyHouseImplA baseA = new BuyHouseImplA();
BuyHouseImplB baseB = new BuyHouseImplB();
BuyHouse proxyA = (BuyHouse) Proxy.newProxyInstance(BuyHouseImplA.class.getClassLoader(),BuyHouseImplA.class.getInterfaces(),new BuyHouseHandler(baseA));
BuyHouse proxyB = (BuyHouse) Proxy.newProxyInstance(BuyHouseImplB.class.getClassLoader(),BuyHouseImplB.class.getInterfaces(),new BuyHouseHandler(baseB));
proxyA.buy();
System.out.println("--------------------");
proxyB.buy();
}
}

运行结果如下:

中介收取好处费
代理A收取5万茶水费
自己排队认筹
付款签订合同

中介收取好处费
代理B收取3万茶水费
自己排队认筹
付款签订合同

那么问题有来了,上面的BuyHouseHandler又是什么东西了?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class BuyHouseHandler implements InvocationHandler {
private BuyHouse base;

public BuyHouseHandler(BuyHouse base) {
this.base = base;
}

@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
if (method.getName().equals("buy")) {
System.out.println("中介收取好处费");
method.invoke(base);
}
return null;
}
}

可以看到,它实现了InvocationHandler接口,并重写了invoke()方法,官方文档解释说,每个代理的实例都有一个与之关联的 InvocationHandler 实现类,如果代理的方法被调用,那么代理便会通知和转发给内部的 InvocationHandler 实现类,由它决定处理,所以 InvocationHandler 是实际执行者。