1.定义
代理模式(Proxy Pattern) :给某一个对象提供一个代理,并由代理对象控制对原对象的引用。代理模式的英文叫做Proxy或Surrogate,它是一种对象结构型模式。
2.uml图
3.代码
上图简单代码实现(静态代理):
package com.wuhuiskiff.www.proxy.code.simple;
/**
* @Auther: 一叶扁舟
* @Date: 2019/2/17 21:31
* @Description:抽象的角色
*/
public interface Subject {
// 客户端的请求
void request();
}
package com.wuhuiskiff.www.proxy.code.simple;
/**
* @Auther: 一叶扁舟
* @Date: 2019/2/17 21:32
* @Description:
*/
public class RealSubject implements Subject {
@Override
public void request() {
System.out.println("真实角色干的事。。。");
}
}
package com.wuhuiskiff.www.proxy.code.simple;
/**
* @Auther: 一叶扁舟
* @Date: 2019/2/17 21:33
* @Description:
*/
public class ProxySubject implements Subject {
private RealSubject realSubject;
public ProxySubject(RealSubject realSubject) {
this.realSubject = realSubject;
}
@Override
public void request() {
this.preRequest();
this.realSubject.request();
this.postRequest();
}
private void preRequest(){
System.out.println("在请求之前,业务处理。。。");
}
private void postRequest(){
System.out.println("在请求之后,业务处理。。。");
}
}
package com.wuhuiskiff.www.proxy.code.simple;
/**
* @Auther: 一叶扁舟
* @Date: 2019/2/17 21:37
* @Description:
*/
public class Client {
public static void main(String[] args) {
RealSubject realSubject = new RealSubject();
Subject subject = new ProxySubject(realSubject);
subject.request();
}
}
(2).动态代理:
package com.wuhuiskiff.www.proxy.code.invoke;
/**
* @Auther: 一叶扁舟
* @Date: 2019/2/17 21:55
* @Description:
*/
public interface Subject {
void request();
}
package com.wuhuiskiff.www.proxy.code.invoke;
/**
* @Auther: 一叶扁舟
* @Date: 2019/2/17 21:56
* @Description:
*/
public class RealSubject implements Subject {
@Override
public void request() {
System.out.println("真实角色所能做的事。。。");
}
}
package com.wuhuiskiff.www.proxy.code.invoke;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* @Auther: 一叶扁舟
* @Date: 2019/2/17 22:03
* @Description:
*/
public class DynamicSubject implements InvocationHandler {
private Object sub;
// 通过构造方法传入一个对象
public DynamicSubject(Object sub) {
this.sub = sub;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before method");
// 其实调用的是被代理对象中的方法,例如这个是调用的是realSubject中的request方法
method.invoke(this.sub, args);
System.out.println("after method");
return null;
}
}
package com.wuhuiskiff.www.proxy.code.invoke;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
/**
* @Auther: 一叶扁舟
* @Date: 2019/2/17 22:06
* @Description:
* 所谓Dynamic Proxy是这样的一种class:它是在运行时生成的class,在生成它时你必须提供一组interface给他
* ,然后改class就宣称它实现了这些interface。你当然可以把该class的实例当做这些interface中的任何一个来用。
* 当然,这个DynamicProxy其实就是一个Proxy,它不会替你作实质性的工作,在生成它的实例时你必须提供一个handler,
* 由它接管实际的工作
*/
public class Client {
public static void main(String[] args) {
Subject subject = new RealSubject();
InvocationHandler handler = new DynamicSubject(subject);
Class<? extends InvocationHandler> classType = handler.getClass();
// 生成一个代理对象,第二参数是RealSubject实现的接口
Subject subject1 = (Subject) Proxy.newProxyInstance(classType.getClassLoader(), subject.getClass().getInterfaces(),
handler);
subject1.request();
// class com.sun.proxy.$Proxy0
System.out.println(subject1.getClass());
}
}
(3)Vector的代理类:
package com.wuhuiskiff.www.proxy.code.vector;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.List;
import java.util.Vector;
/**
* @Auther: 一叶扁舟
* @Date: 2019/2/17 23:40
* @Description:
*/
public class VectorProxy implements InvocationHandler {
private Object object;
public VectorProxy(Object object) {
this.object = object;
}
public static Object factory(Object object){
Class<?> classType = object.getClass();
// 生成代理的实例
VectorProxy vectorProxy = new VectorProxy(object);
return Proxy.newProxyInstance(classType.getClassLoader(),classType.getInterfaces(),vectorProxy);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before method invoke");
if(null != args){
for (Object arg:args) {
System.out.println("参数:" + arg);
}
}
Object result = method.invoke(this.object,args);
System.out.println("after method invoke");
return result;
}
public static void main(String[] args) {
List list = (List) factory(new Vector());
System.out.println(list.getClass());
// 代理类调用method.invoke方法
list.add("张山");
list.add("skiff");
System.out.println("---------------------");
list.remove(0);
}
}
4.优缺点
代理模式的优点
- 代理模式能够协调调用者和被调用者,在一定程度上降低了系统的耦合度。
- 远程代理使得客户端可以访问在远程机器上的对象,远程机器可能具有更好的计算性能与处理速度,可以快速响应并处理客户端请求。
- 虚拟代理通过使用一个小对象来代表一个大对象,可以减少系统资源的消耗,对系统进行优化并提高运行速度。
- 保护代理可以控制对真实对象的使用权限。
代理模式的缺点
- 由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。
- 实现代理模式需要额外的工作,有些代理模式的实现非常复杂。
5.应用
- Java RMI (Remote Method Invocation,远程方法调用)。
- EJB、Web Service等分布式技术都是代理模式的应用。在EJB中使用了RMI机制,远程服务器中的企业级Bean在本地有一个桩代理,客户端通过桩来调用远程对象中定义的方法,而无须直接与远程对象交互。在EJB的使用中需要提供一个公共的接口,客户端针对该接口进行编程,无须知道桩以及远程EJB的实现细节。
- Spring 框架中的AOP技术也是代理模式的应用,在Spring AOP中应用了动态代理(Dynamic Proxy)技术。
6.总结
代理模式包含三个角色:
扫描二维码关注公众号,回复:
12685910 查看本文章

- 抽象主题角色声明了真实主题和代理主题的共同接口;
- 代理主题角色内部包含对真实主题的引用,从而可以在任何时候操作真实主题对象;
- 真实主题角色定义了代理角色所代表的真实对象,在真实主题角色中实现了真实的业务操作,客户端可以通过代理主题角色间接调用真实主题角色中定义的方法。