四(2)、复用类补充之关于代理模式的一点理解

一、关于代理模式的几个概念

1.比如A要去租房,通过中介B,租到C家的房子,这里B就是A的代理。

代理可以认为是之前介绍的组合和继承的折中模式,它有继承的部分也有组合的部分。

2、代理的结构

1)抽象主题角色: 声明了真实主题和代理主题的共同的接口。

2)代理主题角色:内部含有真实主题的引用, 从而可以再任何时候操作真实主体对象;提供了一个与真实主题相同的接口,以便可以替代真实主题。

3)真实主题角色:抽象主题的实现,是具体被代理的对象。

二、三种常见的代理模式

1.普通代理模式

 1 package com.test;
 2
 3 /**
 4  * 抽象主题角色
 5  */
 6 public abstract class Subject {
 7     public abstract void request();
 8 }
 9
10 //-------------分割线--------------------------
11 package com.test;
12
13 /**
14  * 真实主题对象
15  */
16 public class RealSubject extends Subject{
17     @Override
18     public void request() {
19         System.out.println("真实主题对象");
20     }
21 }
22
23 //-------------分割线--------------------------
24 package com.test;
25
26 /**
27  * 代理对象
28  */
29 public class ProxySubject extends Subject{
30
31     private RealSubject realSubject;//代理对象里面放真实对象
32
33     public ProxySubject() {
34
35     }
36
37     @Override
38     public void request() {
39         pre();
40         if (null == realSubject) {
41             realSubject = new RealSubject();
42         }
43         realSubject.request();
44         after();
45     }
46
47     private void pre() {
48         System.out.println("前置");
49     }
50
51     private void after() {
52         System.out.println("后置");
53     }
54
55     public static void main(String[] args) {
56         Subject sub = new ProxySubject();//父类声明,指向子类代理对象
57         sub.request();
58     }
59 }

结果如下:

使用代理模式的优点,是可以在真实请求的前后,加一些控制。使用这种方式,要求知道接口和实现类的信息。

2.使用JDK自带的Proxy,InvocationHandler,Mehtod来实现代理模式(这种是动态代理,对比来讲前一种是静态代理)

 1 package com.test;
 2
 3 /**
 4  * 抽象主题角色
 5  */
 6 public interface Subject { //这里需要是接口,跟上面的例子相比,上面的例子可以写成抽象类,也可以写成接                              //口,但是这个例子里面将只能够写成接口
 7     public abstract void request();
 8 }
 9
10 //-------------------------------分割线----------------------------
11 package com.test;
12
13 /**
14  * 真实主题对象
15  */
16 public class RealSubject implements Subject{
17     @Override
18     public void request() {
19         System.out.println("真实主题对象");
20     }
21 }
22
23 //-------------------------------分割线----------------------------
24 package com.test;
25
26 import java.lang.reflect.InvocationHandler;
27 import java.lang.reflect.Method;
28 import java.lang.reflect.Proxy;
29
30 /**
31  * 创建代理类
32  */
33 public class JDKProxySubject implements InvocationHandler{
34     private Object targetObject;//目标对象, 我们这个工厂就是生产出这个对象的代理对象
35
36     //创建代理对象的具体方法实现
37     public Object createProxyInstance(Object targetObject) {
38
39         this.targetObject = targetObject;
40         /*这个Proxy对象就是jdk自带的一个类,用其newProxyInstance方法
41         来进行创建代理对象, 第一个参数是类加载器, 第二个参数是实现的接口数组
42         第个参数记住用this即可 ,这么理解,他就是一个句柄,
43         给别人握的, 这个句柄对象需要实现InvocationHandler接口*/
44         return Proxy.newProxyInstance(this.targetObject.getClass().getClassLoader(),
45             this.targetObject.getClass().getInterfaces(),this);
46     }
47
48
49     @Override
50     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
51
52         pre();//前置处理
53         Object result = null;
54         result = method.invoke(this.targetObject,args);
55         after();//后置处理
56         return result;
57     }
58
59     private void pre() {
60         System.out.println("前置");
61     }
62
63     private void after() {
64         System.out.println("后置");
65     }
66
67     public static void main(String[] args) {
68         JDKProxySubject factory = new JDKProxySubject();//创建工厂
69         Subject proxySubject = (Subject)factory.createProxyInstance(new RealSubject());
70         proxySubject.request();
71     }
72 }

结果同1

这个例子中,首先请关注下Subject处, 上一个例子中Subject是抽象类(换成接口也可以),但是这个例子中,只能使用接口。因为由createProxyInstance

方法生成的代理对象,实际上是Proxy类的一个子类,所以这里向上转型时Subject为接口才适合。使用这种方式,要求提前知道接口信息即可。

3.使用工具CGlib实现动态代理,需要导入cglib的jar

 1 package com.test;
 2
 3 import java.lang.reflect.Method;
 4
 5 import net.sf.cglib.proxy.Enhancer;
 6 import net.sf.cglib.proxy.MethodInterceptor;
 7 import net.sf.cglib.proxy.MethodProxy;
 8
 9 public class CGlibProxyFactory implements MethodInterceptor{
10     private Object targetObject;
11
12     public Object createProxyInstance(Object targetObject) {
13         pre();
14         this.targetObject = targetObject;
15         Enhancer enhance = new Enhancer();//创建一个类
16         enhance.setSuperclass(this.targetObject.getClass());//非final方法进行覆盖
17         enhance.setCallback(this);//设置回调为本身
18         after();
19         return enhance.create();
20     }
21
22     private void pre() {
23         System.out.println("前置");
24     }
25
26     private void after() {
27         System.out.println("后置");
28     }
29
30
31     @Override
32     public Object intercept(Object proxy, Method method, Object[] args,
33             MethodProxy arg3) throws Throwable {
34
35         Object result = null;
36         result = method.invoke(this.targetObject, args);
37         return result;
38     }
39
40     public static void main(String[] args) {
41         CGlibProxyFactory factory = new CGlibProxyFactory();
42         Subject subject = (Subject)factory.createProxyInstance(new RealSubject());
43         subject.request();
44     }
45 }

结果同1

使用CGlib的方式,跟上一种Proxy的方式相比,甚至连接口都不需要提前知道。(性能差点)

三、关于代理模式和另几个模式之前的关系

1.代理模式和适配器模式:粗看上去它们都可以视为一个对象提供一种前置的接口,但是适配器模式的用意在于要改变所使用的接口,而代理模式并不能改变对象的接口。

2.代理模式和装饰模式:装饰模式是要为所装饰的对象增强功能,而代理模式是对对象的使用施加控制。

时间: 2024-12-06 19:05:29

四(2)、复用类补充之关于代理模式的一点理解的相关文章

关于代理模式的个人理解

静态代理模式: 实际上使用的时候,某些接口的实现类满足不了条件,或者想改变少部分方法的实现.采用静态代理模式 静态代理实际上新实现一个接口, 但是这个类里面有一个 老的实现类的引用. 重写需要改变的方法, 不许改变的方法直接调用老的方法就好 动态代理模式: 如果采用静态代理发现相同的代码太多了. 可以该用动态代理代码 在invoke方法里面讲 共同代码写在哪里. 特殊的采用 : if(Connection.class.isAssignableFrom(proxy.getClass()) &&

Think in Java(四):复用类

1. 每一个非基本类型的对象都有一个toString方法,而且当编译器需要一个String而你却只有一个对象时,该方法便会被调用. public class SprinklerSystem { private String valve: public String toString() { value = "test"; return "valve = " + valve; } public static void main(String[] args) { Spr

<四>读<<大话设计模式>>之代理模式

代理模式我想大家即便不熟悉也都听过吧,从字面意思上看就是替别人干活的,比方代理商.在项目的实际应用中也有非常多地方用到.比方spring通过代理模式生成对象等. 代理模式的书面定义:为其它对象提供一种代理以控制对这个对象的訪问. 在某些情况下,一个对象不适合或者不能直接引用还有一个对象,而代理对象能够在client和目标对象之间起到中介的作用. 在<<大话设计模式>>一书中以一个有男朋友的女孩让"小菜"帮忙修电脑的故事展开的,事实上说白了代理就是帮别人干活的,一

&lt;四&gt;读&lt;&lt;大话设计模式&gt;&gt;之代理模式

代理模式我想大家即便不熟悉也都听过吧,从字面意思上看就是替别人干活的,比如代理商.在项目的实际应用中也有很多地方用到,比如spring通过代理模式生成对象等. 代理模式的书面定义:为其他对象提供一种代理以控制对这个对象的访问.在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用. 在<<大话设计模式>>一书中以一个有男朋友的女孩让"小菜"帮忙修电脑的故事展开的,其实说白了代理就是帮别人干活的,一般老板不出面,

设计模式(四)——代理模式(Proxy)

代理模式的参与者有:一个约束.一个代理者.一个被代理者.一个调用者 代理模式的实现很简单:还是那个房子,对于开门这个操作,我更换了一个远程解锁的门,那么我就可以通过这个远程连接的服务器远程解锁,这样我家里人没带钥匙,我也可以远程解锁了,而且不需要钥匙,甚至完全不需要知道锁的存在,我代码实现一下 /// <summary> /// 抽象接口 用来进行约束 /// </summary> public interface IAccess { void Access(); } /// &l

【设计模式】-代理模式

模式动机 在某些情况下,一个客户不想或者不能直接引用一个对 象,此时可以通过一个称之为"代理"的第三者来实现 间接引用.代理对象可以在客户端和目标对象之间起到 中介的作用,并且可以通过代理对象去掉客户不能看到 的内容和服务或者添加客户需要的额外服务. 通过引入一个新的对象(如小图片和远程代理 对象)来实现对真实对象的操作或者将新的对 象作为真实对象的一个替身,这种实现机制即 为代理模式,通过引入代理对象来间接访问一 个对象,这就是代理模式的模式动机. 模式定义 代理模式(Proxy P

设计模式——代理模式与装饰模式的异同

两种模式的特点 装饰模式: 在不改变接口的前提下,动态扩展对象的访问. 动态继承,让类具有在运行期改变行为的能力. 装饰模式,突出的是运行期增加行为,这和继承是不同的,继承是在编译期增加行为. 强调:增强 代理模式: 在不改变接口的前提下,控制对象的访问. 1.从封装的角度讲,是为了解决类与类之间相互调用而由此导致的耦合关系,可以说是接口的另外一个层引用. 比如:在a类->b代理->c类这个关系中,c类的一切行为都隐藏在b中.即调用者不知道要访问的内容与代理了什么对象. 2.从复用的角度讲,可

代理模式与Android

代理模式(Proxy) 一.   什么是代理模式 先来看看官方的说法,代理模式就是为其它对象提供一种代理,以控制对这个对象的訪问. 看来这个官方的说法的确有点官方,看了还是让人感觉不点不知所措,还是不明确代理模式是什么,到底是用来做什么的. 事实上代理这个名词,对于我们来说事实上并不陌生,生活中有非常多关于代理的样例.比如校园代理等,就以校园代理来讲,这个校园代理就是为他相应的上司的作代理,而这个校园代理的工作就是訪问校园中的学生,比如对学生进行问卷之类的事.在这个样例中,学生就是官方说法中的其

为其他对象提供一种代理以控制对这个对象的访问-代理模式

一.前言 在某些情况下,一个客户不想或者不能直接引用一个对 象,此时可以通过一个称之为“代理”的第三者来实现 间接引用.代理对象可以在客户端和目标对象之间起到 中介的作用,并且可以通过代理对象去掉客户不能看到 的内容和服务或者添加客户需要的额外服务. 通过引入一个新的对象来实现对真实对象的操作或者将新的对 象作为真实对象的一个替身,这种实现机制即 为代理模式,通过引入代理对象来间接访问一 个对象,这就是代理模式的模式动机. 在代理模式(Proxy Pattern)中,一个类代表另一个类的功能.这