sunxin's Studio.

代理设计模式

字数统计: 994阅读时长: 3 min
2018/09/08 Share

代理设计模式

概述

为目标对象提供一个代理对象,然后让代理对象控制对目标对象的引用。

  • 静态代理:代理类在编译时就已实现好,Java编译完成后代理类就是一个.class文件
  • 动态代理:代理类在运行时生成,在运行时动态生成class文件并加载到jvm中

Uml图

使用场景

生活中很多场景都会用到代理模式,最直观的例子就是代购,比如你想要买一款最新的电子产品,但是国内没有,只能找代购到国外淘宝,那么“你”就是一个目标对象,代购者就是一个代理对象,让代购者帮你去买你所想要的东西即可。

静态代理

代码走一波

  1. 首先我有一个愿望,就是买一辆奥迪,或者想买很多稀奇古怪的东西创建一个接口声明你想让代购帮你买的东西
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* 愿望
* @author sunxin
*
*/
public interface IWish {
/**
* 买一辆奥迪
*/
void buyAudi();

/**
* 买一台电脑
*/
void buyIMac();
}
  1. 创建真实对象类,就是我
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Me implements IWish{

@Override
public void buyAudi() {
System.out.println("刷卡付钱");
System.out.println("试驾");
System.out.println("...");
}

@Override
public void buyIMac() {
System.out.println("刷卡付钱");
System.out.println("试用");
System.out.println("...");
}

}
  1. 创建代理类(Proxy),即代购者,通过代理类的构造函数获取真实对象我,间接的执行方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class Saler implements IWish{


private IWish me;

public Saler(IWish me){
this.me = me;
}

@Override
public void buyAudi() {
System.out.println("办理一系列买车业务");
//我自己负责出钱等
me.buyAudi();
System.out.println("买车业务办理完毕");
}

@Override
public void buyIMac() {
System.out.println("办理一系列买Mac业务");
me.buyIMac();
System.out.println("买Mac业务办理完毕");
}

}
  1. 最后调用
1
2
3
4
5
6
7
8
9
public class ProxyClient {
public static void main(String[] args) {
Me me = new Me();
IWish saler = new Saler(me);
saler.buyAudi();
System.out.println("--------");
saler.buyIMac();
}
}

输出结果为:

办理一系列买车业务
刷卡付钱
试驾

买车业务办理完毕
/——–
办理一系列买Mac业务
刷卡付钱
试用

买Mac业务办理完毕

  • 通过代购这个例子应该很容易就理解了代理模式
静态代理的优缺点

优点

  • 降低了代码的耦合度

缺点

  • 会发现代码优点冗余
  • 增加了一个代理对象,会造成请求速度变慢

动态代理

Java中提供了对动态代理的封装,代码中的注释还是比较清楚的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
public class DynamicProxyClient {
public static void main(String[] args) {
IWish me = new Me();
/**
* 参数一:类加载器对象,即哪个类加载器加载这个代理类到jvm的方法区
* 参数二:接口,表名自己的代理类需要实现哪个接口
* 参数三:指定代理类中都需要做什么
*/
IWish proxy = (IWish) Proxy.newProxyInstance(IWish.class.getClassLoader(), // 类加载器
new Class<?>[] { IWish.class }, // 接口类数组
new WishInvocationHandler(me));// 回调接口

proxy.buyAudi();
System.out.println("=================");
proxy.buyIMac();

}


/**
* 指定运行时将生成的代理类要完成的具体任务,代理类调用任何方法都会经过该类
* @author sunxin
*
*/
public static class WishInvocationHandler implements InvocationHandler {
private IWish me;
public WishInvocationHandler(IWish me){
this.me = me;
}
/**
* 这个方法在代理对象调用任何方法的时候都会被调用,方法不同会导致第二个method的
* 不同,
* @param proxy 代理对象
* @param method 表示被哪个方法调用了
* @param args 指定调用方法的参数
* @return
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代购前一些需要做的事情");
//执行方法
method.invoke(me, args);
System.out.println("代购完毕");
return null;
}
}
}
动态代理的优缺点

优点

  • 减少了代理类中的很多重复性代码,更注重操作过程
  • 由于Java的单继承性,只能针对接口创建代理类,不能针对类创建代理类
CATALOG
  1. 1. 代理设计模式
    1. 1.1. 概述
    2. 1.2. 使用场景
      1. 1.2.1. 静态代理
        1. 1.2.1.1. 静态代理的优缺点
      2. 1.2.2. 动态代理
        1. 1.2.2.1. 动态代理的优缺点