插件化开发笔记(一)代理模式

代码实现

   从编码的角度来说,代理模式分为静态代理和动态代理,可以结合下面的例子来理解。(1)静态代理,在代码运行前代理类的class文件就已经存在了,结合下面的代码直观的理解就是,代理类Assistant类是写死的,在运行前这个编译类Assistant.class就存在了。(2)动态代理,则是在代码运行时才会通过反射来动态地生成代理类对象,并确定到底来代理谁。也就是说,我们在编码阶段并不会定义出这个代理类,而是在运行的时候动态生成。从下面的代码实现中,我们发现,动态代理实现时,并没有出现Assistant这个类。

   下面我们来用代码实现静态代理和动态代理。

1、静态代理

复制代码
1 //Subject:抽象主题类,定义了老板和助理的这次行为
2 public interface IShop {
3 void buy();
4 }
5
6 //RealSubject:真实主体类。实现了抽象主题接口
7 public class Boss implements IShop {
8 @Override
9 public void buy() {
10 System.out.println(“I am boss,I buy buy buy”);
11 }
12 }
13
14 //Proxy:代理类。以组合的方式持有了对真实主题类Boss的引用,也实现了抽象主题接口。在实现的buy方法中,调用了真实主题Boss的对应方法。
15 public class Assistant implements IShop {
16 private IShop mBoss;
17 Assistant(IShop shoper) {
18 mBoss = shoper;
19 }
20
21 @Override
22 public void buy() {
23 mBoss.buy();
24 }
25 }
26
27 //Client:客户端类
28 public class ProxyDemo {
29 public static void main(String[] args) {
30 IShop boss = new Boss();
31 IShop assitant = new Assistant(boss);
32 assitant.buy();
33 }
34 }
复制代码
运行结果

I am boss,I buy buy buy
这里我们可以看到,Client类中调用的是代理Assistant的buy方法,而实际完成的是委托者Boss的buy方法,从而实现了这次代理行为。

2、动态代理

复制代码
1 public interface IShop {
2 void buy();
3 }
4
5 public class Boss implements IShop {
6 @Override
7 public void buy() {
8 System.out.println(“I am boss,I buy buy buy”);
9 }
10 }
11
12 //Java提供了动态的代理接口InvocationHandler,实现该接口需要重写invoke方法。
13 import java.lang.reflect.InvocationHandler;
14 import java.lang.reflect.Method;
15
16 public class DynamicProxy implements InvocationHandler {
17 private Object mObject;
18
19 DynamicProxy(Object object) {
20 mObject = object;
21 }
22
23 @Override
24 public Object invoke(Object proxy, Method method, Object[] objects) throws Throwable {
25 System.out.println(“invoke methodName=” + method.getName());
26 method.invoke(mObject, objects);
27 return null;
28 }
29 }
30
31 //Client
32 import java.lang.reflect.InvocationHandler;
33 import java.lang.reflect.Proxy;
34
35 public class Client {
36 public static void main(String[] args) {
37 //创建boss类
38 IShop boss = new Boss();
39 //创建动态代理
40 InvocationHandler proxyHandler = new DynamicProxy(boss);
41 ClassLoader classLoader = boss.getClass().getClassLoader();
42 //动态创建代理类
43 IShop assitant = (IShop) Proxy.newProxyInstance(classLoader, new Class[]{IShop.class}, proxyHandler);
44 assitant.buy();
45 }
46 }
复制代码
运行结果

invoke methodName=buy
I am boss,I buy buy buy
在动态代理类DynamicProxy中,声明了一个Object的引用,该应用指向被代理类对象(该实例中指向的就是Boss类对象),我们调用被代理类对象(Boss对象)的具体方法(该例子中指buy方法)会在invoke方法中执行。在Client类中的Proxy.newProxyInstance()来生成动态代理类对象assistant,而调用assistant.buy()方法时会调用DynamicProxy类中的invoke方法,这样就间接地调用了Boss类中的buy()方法,从而实现了动态代理。

四、静态代理和动态代理对比

   说到使用动态代理的好处,可能得一大篇文章才说得清楚,在这里我只想提一点,就是动态代理下,直到运行时才会生成代理类,当代理场景比较多时,可以节约很多不必要的浪费。这里我们比较一下,有多个代理场景时,静态代理和动态代理的表现。

1、静态代理实现多个代理场景

复制代码
1 public interface IShop {
2 void buy();
3 }
4
5 public class Boss implements IShop {
6 @Override
7 public void buy() {
8 System.out.println(“I am boss,I buy buy buy”);
9 }
10 }
11
12 public class Assistant implements IShop {
13 private IShop mBoss;
14 Assistant(IShop shoper) {
15 mBoss = shoper;
16 }
17
18 @Override
19 public void buy() {
20 mBoss.buy();
21 }
22 }
23
24 public interface IDrive {
25 void drive();
26 }
27
28 public class Leader implements IDrive {
29 @Override
30 public void drive() {
31 System.out.println(“I am leader,I drive drive drive”);
32 }
33 }
34
35 public class Driver implements IDrive {
36 private IDrive mLeader;
37
38 Driver(IDrive driver) {
39 mLeader = driver;
40 }
41
42 @Override
43 public void drive() {
44 mLeader.drive();
45 }
46 }
47
48 public class ProxyDemo {
49 public static void main(String[] args) {
50 IShop boss = new Boss();
51 IShop assitant = new Assistant(boss);
52 assitant.buy();
53
54 IDrive leader = new Leader();
55 IDrive driver = new Driver(leader);
56 driver.drive();
57 }
58 }
复制代码
运行结果

I am boss, I buy buy buy
I am leader,I drive drive drive
如上代码实际上就是两个代理场景的叠加,增加一个场景,代码量增加一倍。

2、动态代理实现多个代理场景

复制代码
1 public interface IShop {
2 void buy();
3 }
4
5 public class Boss implements IShop {
6 @Override
7 public void buy() {
8 System.out.println(“I am boss,I buy buy buy”);
9 }
10 }
11
12 public interface IDrive {
13 void drive();
14 }
15
16 public class Leader implements IDrive {
17 @Override
18 public void drive() {
19 System.out.println(“I am leader,I drive drive drive”);
20 }
21 }
22
23 //动态代理类
24 import java.lang.reflect.InvocationHandler;
25 import java.lang.reflect.Method;
26
27 public class DynamicProxy implements InvocationHandler {
28 private Object mObject;
29
30 DynamicProxy(Object object) {
31 mObject = object;
32 }
33
34 @Override
35 public Object invoke(Object proxy, Method method, Object[] objects) throws Throwable {
36 System.out.println(“invoke methodName=” + method.getName());
37 method.invoke(mObject, objects);
38 return null;
39 }
40 }
41
42 //Client
43 import java.lang.reflect.InvocationHandler;
44 import java.lang.reflect.Proxy;
45
46 public class Client {
47 public static void main(String[] args) {
48 IShop boss = new Boss();
49 InvocationHandler proxyHandler = new DynamicProxy(boss);
50 ClassLoader classLoader = boss.getClass().getClassLoader();
51 IShop assitant = (IShop) Proxy.newProxyInstance(classLoader, new Class[]{IShop.class}, proxyHandler);
52 assitant.buy();
53 }
54 }
复制代码
运行结果

invoke methodName=buy
I am boss, I buy buy buy
invoke methodName=drive
I am leader,I drive drive drive
龙华大道1号http://www.kinghill.cn/LongHuaDaDao1Hao/index.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值