1、定义
代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问;
代理模式也叫做委托模式,是一种使用频率非常高的设计模式;在生活中有一种职业可以非常好的体现代理模式 — 中介;
2、类图
代理模式的通用类图如下:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiQDOxEzX3xCZlhXam9VbsUmepNXZy9CXwJWZ3xCdh1mcvZ2Lc1zaHRGcWdUYuVzVa9GczoVdG1mWfVGc5RHLwIzX39GZhh2csATMflHLwEzX4xSZz91ZsAzMfRHLGZkRGZkRfJ3bs92YskmNhVTYykVNQJVMRhXVEF1X0hXZ0xiNx8VZ6l2cssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL2MjN4MDNxYzYkBjMjJzMzYzXxQzNycTM3IzLclDMyIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
代理模式的结构很简单,主要是通过定义一个继承抽象主题的代理来包含真实主题,从而实现对真实主题的访问控制,各部分组成如下:
- 抽象主题(Subject)类:可以是抽象类也可以是接口,是一个最普通的业务类型定义,无特殊要求;
- 真实主题(Real Subject)类:实现了抽象主题中的具体业务,是代理对象所代表的真实对象,是最终要引用的对象;
- 代理(Proxy)类:提供了与真实主题相同的接口,其内部含有对真实主题的引用,它可以访问、控制或扩展真实主题的功能。
3、代码实现
抽象主题 的Java代码实现如下:
interface Subject {
void Request();
}
真实主题 的Java代码实现如下:
class RealSubject implements Subject {
public void Request() {
System.out.println("访问真实主题方法...");
}
}
代理类 的Java代码实现如下:
class Proxy implements Subject {
private RealSubject realSubject;
public void Request() {
if (realSubject == null) {
realSubject = new RealSubject();
}
preRequest();
realSubject.Request();
postRequest();
}
public void preRequest() {
System.out.println("访问真实主题之前的预处理。");
}
public void postRequest() {
System.out.println("访问真实主题之后的后续处理。");
}
}
4、特点
优点:
1、职责清晰,降低了系统的耦合度;
真实主题就是实际的业务逻辑,无需关心其他业务逻辑,通过代理完成整个完整的功能,软件功能划分简洁清晰。
2、高扩展性;
代理对象可以扩展目标对象的功能;
3、保护敏感对象;
在使用者与目标对象之间起到一个中介作用和保护目标对象的作用;
缺点:
1、会造成系统设计中类的数量增加;
2、代理对象容易成为性能瓶颈;
3、增加了系统的复杂度;
5、适用场景
当无法或不想直接引用某个对象或访问某个对象存在困难时,可以通过代理对象来间接访问;
使用代理模式主要有两个目的:一是保护目标对象,二是增强目标对象。
6、动态代理
上述的代理模式,我们需要自己实现代理类,这是方式叫做静态代理;
静态代理存在两个缺点:
- 真实主题与代理主题一一对应,增加真实主题也要增加代理;
- 设计代理类之前真实主题必须事先存在,缺少灵活性;
采用动态代理模式可以解决以上问题;动态代理是在实现阶段不用关心代理谁,而在运行阶段才指定代理哪一个对象。
而在Java 中,JDK帮我们封装好了动态代理相关的类,可以非常轻松的实现动态代理;
6.1 Java中的动态代理类
Java动态代理类位于java.lang.reflect包下,主要涉及到以下一个接口和一个类:
1、InvocationHandler 接口
该接口中仅定义了一个方法
public object invoke(Object obj,Method method, Object[] args)
参数obj 指 被代理类,method是 被代理的方法,args为该方法的参数数组;
2、Proxy 动态代理类
该类即为动态代理类,其中主要包含以下内容:
//构造函数,用于给内部的InvocationHandler赋值
protected Proxy(InvocationHandler h)
//获得一个代理类,其中loader是类装载器,interfaces是真实类所拥有接口的数组
static Class getProxyClass (ClassLoaderloader, Class[] interfaces)
//返回被代理类的一个实例,返回后的Object可以当作被代理类使用
static Object newProxyInstance(ClassLoaderloader, Class[] interfaces, InvocationHandler h)
6.2 JDK动态代理机制的使用
主要分为两个步骤:
第一步:实现InvocationHandler
public class InvocationHandlerImpl implements InvocationHandler
{
//要代理的真实对象
private Object subject;
//构造方法,给我们要代理的真实对象赋初值
public InvocationHandlerImpl(Object subject)
{
this.subject = subject;
}
/**
* 集中处理动态代理类上的所有方法调用。
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
//在代理真实对象前可以添加一些自己的操作
....
//执行要调用的方法
Object returnValue = method.invoke(subject, args);
//在代理真实对象后我们也可以添加一些自己的操作
....
return returnValue;
}
}
第二步:调用Proxy.newProxyInstance生成动态代理类实例
public class DynamicProxyDemo
{
public static void main(String[] args)
{
//代理的真实对象
Subject realSubject = new RealSubject();
//创建InvocationHandlerImpl对象
InvocationHandler handler = new InvocationHandlerImpl(realSubject);
//生成动态代理类实例
ClassLoader loader = realSubject.getClass().getClassLoader();
Class[] interfaces = realSubject.getClass().getInterfaces();
Subject subject = (Subject) Proxy.newProxyInstance(loader, interfaces, handler);
//使用动态代理类实例
subject.doSomething();
}
}
6.3 JDK动态代理机制的原理
此部分不是本文的重点,感兴趣的同学可以自行阅读源码,大体上可以分为四步骤:
- 通过实现 InvocationHandler 接口创建自己的调用处理器;
- 通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类;
- 通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;
- 通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。
本文参考了:Java JDK 动态代理(AOP)使用及实现原理分析
我的视频课
下面是我录制的一些视频课,欢迎大家围观~《设计模式修炼真经》 设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结,代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。 本套课程深入介绍了经典的23种设计模式,并加入了自己的感悟,希望大家能够彻底掌握设计模式,写出最好的代码,达到无招胜有招的境界,最终超越这23种设计模式。
《彻底搞定JVM》 JVM是Java中重要的也是较难理解的内容; 面试者对JVM的了解程度某种程度上反映了面试者技术深度,所以JVM也是面试时经常考察的内容; 本课程从JVM运行流程、数据运行时区域组成部分、类加载机制、垃圾回收机制、内存模型、常见面试题讲解等角度出发,帮你彻底搞定JVM,拿下心仪Offer;
《Android性能优化参考》 本课程包含了Android中的App启动优化、UI优化、内存优化、图片优化、耗电量等常见的性能优化场景,通过学习此课程,你将对整个Android性能优化体系有清晰的认识。
性能优化作为Android高级开发的必备技能,也是大厂面试必考的题目,是体现一个人技术深度最好的试金石。
《面试之排序算法》 排序算法是我们面试被问到最多的基础算法,本课程详细介绍了七种排序算法,包括插入排序、选择排序、冒泡排序、谢尔排序、快速排序、堆积排序和二路并归排序。每种算法都详细介绍了核心思想、详细步骤、时间复杂度和代码实现,希望帮助大家深入理解排序算法,搞定面试!
《Android HyBrid App开发实战》 本课程为Android HyBrid App开发实战课程,由浅入深,从三种App的历史和特点开始,介绍了Android WebView的使用、Java和JS交互的原生方式、著名的WebView安全漏洞、JSBridge的原理和使用,最后通过一个网上商城的实战综合全部内容,让同学们掌握并深入理解Android HyBrid App开发。
《AI导论》 介绍人工智能AI的诞生历史和到现在为止的不同发展阶段;介绍了AI领域中常见的名词概念和其关系,包括机器学习、深度学习、神经网络结构搜索 NAS、生成对抗网络 GAN等;最后对AI发展做出展望。 本课程属于导论课程,旨在帮助同学们从宏观层面把握AI,建立AI的知识体系。
《Java注解精讲》 本课程详细介绍了Java中的注解机制,包括注解的定义和分类,注解的使用和自定义,注解的源码和架构分析; 本课程语言简单凝练,视频短小精悍,让你一次彻底搞懂Java注解!
《Java反射精讲》 反射是Java中重要的也是较难理解的内容;
本课程从反射的定义、作用、原理和使用出发,全方位帮你彻底搞定反射;
您的点赞是我前进的动力~