内容简介:插件化开发所涉及到的技术点非常多,比如程序的启动流程、四大组件启动流程、ClassLoader原理、上下文Context、AMS原理、反射、代理等。本篇主要简单介绍代理模式(实际上只是一篇学习笔记),为后面介绍插件化实现做知识铺垫。定义:为其他对象提供一种代理,以控制对这个对象的访问,这种形式称为代理模式。(看起来挺抽象的,不好理解,能理解下面的解释就够了)代理模式也叫委托模式,是结构性设计模式的一种。在现实生活中,我们用到类似代理模式的场景非常多,比如买房者找房屋中介买房、受害者委托律师打官司、老板安排助
前言
插件化开发所涉及到的技术点非常多,比如程序的启动流程、四大组件启动流程、ClassLoader原理、上下文Context、AMS原理、反射、代理等。本篇主要简单介绍代理模式(实际上只是一篇学习笔记),为后面介绍插件化实现做知识铺垫。
一、定义
定义:为其他对象提供一种代理,以控制对这个对象的访问,这种形式称为代理模式。(看起来挺抽象的,不好理解,能理解下面的解释就够了)
代理模式也叫委托模式,是结构性 设计模式 的一种。在现实生活中,我们用到类似代理模式的场景非常多,比如买房者找房屋中介买房、受害者委托律师打官司、老板安排助理采购等。这些场景有一个共同特点:真正想做某件事的人 ,因为行业壁垒等各种原因自己不容易完成,于是转而找其他专业人士来替自己完成这个意愿。以老板安排助理采购电脑设备为例:老板(即委托者)是真是需要购买电脑设备的人,但由于缺乏对电脑设备的了解,于是委派助理(即代理)来完成自己的这次采购意愿。
二、角色及结构
在代理模式中,包含了如下的角色:
Subject:抽象主题类,声明真实主题与代理的共同接口方法。也就是定义一个接口,定义老板和助理的这次行为:采购!
RealSubject:真实主题类,定义了代理所表示的集体对象,客户端通过代理类间接调用真实主题类的方法。即老板,真正需要采购的人。
Proxy:代理类,持有对真实主题类的引用,在其所实现的接口方法中调用真实主题类中相应的接口方法执行。即助理,以老板的名义去采购。
Client:客户端类。也就是一段逻辑代码,将上述角色组织起来,完成这次采购行为。
类结构图如下:
三、代码实现
从编码的角度来说,代理模式分为静态代理和动态代理,可以结合下面的例子来理解。(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
由于不需要单独实现代理类,多个代理场景下实际上就节约了很多的代码量。
结语
代理模式作为设计模式中的一种,使用比较广泛,内容非常多,笔者知识有限,暂时先介绍这么多,希望能帮助初学者能够掌握代理模式的基本知识和使用。
以上所述就是小编给大家介绍的《插件化开发笔记(一)代理模式》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- KodExplorer 4.06 发布,全面开放,支持完整插件模式
- IDEA 插件:多线程文件下载插件开发
- 从头开发一个Flutter插件(二)高德地图定位插件
- Gradle插件开发系列之gradle插件调试方法
- Gradle插件开发系列之开发第一个gradle插件
- WordPress插件开发 -- 在插件使用数据库存储数据
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
A Project Guide to UX Design
Russ Unger、Carolyn Chandler / New Riders Press / 2009-3-23 / USD 39.99
"If you are a young designer entering or contemplating entering the UX field this is a canonical book. If you are an organization that really needs to start grokking UX this book is also for you. " -......一起来看看 《A Project Guide to UX Design》 这本书的介绍吧!