什么是代理模式?相信有很多朋友都有这个疑惑,不知道代理模式能解决什么问题,不知道为什么要有代理模式,看完本篇相信不明白的朋友会对代理模式有新的理解。
我们先来看一下较为简单的静态代理。
一、静态代理设计模式
1. 为什么需要代理设计模式
1.1 问题
-
在JavaEE分层开发开发中,那个层次对于我们来讲最重要
我们学了很久的MVC分层架构,那么对于我们而言,那个层次最重要 DAO ---> Service --> Controller 我们认为JavaEE分层开发中,最为重要的是Service层 ,因为我们的所有 核心业务功能都是在service层中实现
-
Service层中包含了哪些代码?
Service层中 = 核心功能(几十行 上百代码) + 额外功能(附加功能) 1. 核心功能 业务运算 DAO调用 2. 额外功能 1. 不属于业务 2. 可有可无 3. 代码量很小 比如事务,我们在增删改的时候需要添加事务,在查询的时候我们可能就不需要开启 比如日志,我们可以加入日志来帮助我们更好的发现问题,我们在一些无关的地方就 不需要加入,以免出现大量无用的日志违背我们的目的。比如我们需要知道程序的性 能如何,我们在方法前后获取时间戳来计算程序运行的时间。。。。。 这些功能我们都可以叫做额外的功能。
-
这些额外功能写在Service层中好不好?
Service层的调用者的角度(Controller):需要在Service层书写额外功能。比如我们需要事务来控制
此次的运行是否需要回滚
软件设计者角度:Service层不需要额外功能,认为什么层次就只需要干什么事情,
这些额外的功能不应该出现在service层中
1.2 现实生活中我们遇到的问题,以及如何解决
上面说了那么多,可能我们还是不清楚代理设计模式到底能解决什么问题?
接下来我们看一个实际生活中的例子,来理解代理模式。
我觉得最经典的例子就是 租房
租房我们要有 房东 和 租客,我们可以将他们两个写成两个类
class 租客{ //调用者action
}
class 房东{ //service
打广告(){
}
带租客看房(){
}
签合同收钱(){
}
}
对于房东来讲,核心功能是什么呢?当然是签合同收钱了(核心功能)
打广告,带人看房什么的太累了(额外功能),可是不做又租不出去
房东心想,要是打广告,带人看房什么的都让别人做,我就只负责收钱那多好。
这就出现了新的职业------>中介(代理)
中介负责打广告,带租客看房,然后由房东来和租客签合同。
同理,我们将中介写成一个类。
此时房东的方法就只保留核心方法(签合同收钱)
class 房东{
签合同收钱(){
}
}
class 中介{ //Proxy 中介需要有与房东相同的方法名来迷惑租客
打广告(){ //由中介来做额外功能
}
带租客看房(){
}
签合同收钱(){
房东.签合同收钱(); //核心功能 调用房东的方法
}
}
2. 代理设计模式
2.1 概念
通过代理类,为原始类(目标)增加额外的功能
好处:利于原始类(目标)的维护
2.2名词解释
1. 目标类 原始类
指的是 业务类 (核心功能 --> 业务运算 DAO调用)
2. 目标方法,原始方法
目标类(原始类)中的方法 就是目标方法(原始方法)
3. 额外功能 (附加功能)
日志,事务,性能
2.3 代理开发的核心要素
代理类 = 目标类(原始类) + 额外功能 + 原始类(目标类)实现相同的接口
房东 ---> public interface UserService{ //原始类实现的接口
m1
m2
}
UserServiceImpl implements UserService{ //原始类
m1 ---> 业务运算 DAO调用(核心方法/功能)
m2
}
UserServiceProxy implements UserService{ //代理类实现与原始类相同的接口
//为了有与原始类相同的方法名
m1
m2
额外功能
}
2.4 编码
静态代理:需要为每一个原始类,手工编写一个代理类 (.java .class)
3.静态代理存在的问题
1. 我们要为每个原始类都要编写一个代理类,静态类文件数量过多,不利于项目管理
UserServiceImpl ----> UserServiceProxy
OrderServiceImpl -----> OrderServiceProxy
2. 额外功能维护性差
代理类中 额外功能修改复杂(麻烦),因为要逐个修改
上面是我们所说的静态代理,可以为我们的原始类(目标类)增加额外的功能而不影响原始类,易于原始类的维护,但是缺点也很明显,每个原始类都要有其对应的代理类,代理文件过多,而且代理类中的额外功能不易修改。
这些问题改如何解决,就要通过动态代理来解决。动态代理的本质和静态代理没有区别,只是解决了静态代理出现的问题。
详细的动态代理内容,请看我的另外一篇博客: