设计模式详解(五)--------代理模式
文章目录
1. 相关
所谓的代理者是指一个类别可以作为其它东西的接口。代理者可以作任何东西的接口:网上连接、存储器中的大对象、文件或其它昂贵或无法复制的资源。
2. 个人理解
代理模式你不清楚的话,你肯定也接过生活中的代理商吧?代理模式与代理商的作用差不多。
我们搞一个代理商有什么用?
1.保护了供应商,不至于让客户直接与供应商扯皮
2.增加可操作空间,比如我想在你获取到商品的时候加价
3.减小互相之间的依赖性,在程序中体现为减小耦合
增加一个环节,当然也是有一定劣势的:
1.步骤过多,增加了交易的耗时
2.让交易看起来很复杂
那么如果你能看懂上面三点,你对代理模式的优缺点和运行模式就有一定理解了,下面我们来看一下程序中的代理模式。
3. 代理模式结构
在我们上面的举例中,旧大致体现出了代理模式的大致结构:服务商,代理商,客户端。
服务商:提供客户所需的实例
代理上:从服务商那里获取实例并提供一个接口给客户端,客户端从接口获取实例
客户端:获取并消费实例
思维导图
4. 实例
4.1. 实例场景
我们现在有一个计费方法,调起计费时需要请求第三方,有以下需求
不希望客户端能够直接获取这个计费实例,这样非常的不安全
希望客户端每次访问这个计费的时候,进行日志记录请求参数
希望获取计费结束后进行日志记录请求计费情况
4.2. 程序设计
公共接口:为了方便获取,我们需要先为所有服务商和代理提供一个公共接口,这个接口规定了我们根据服务商所提供 的所有服务。
服务商:在此示例,服务商只打印一个日志来代表获取实际计费服务。
代理商:继承公共接口,并通过接口方法获取服务商的实际服务;在获取计费之前和之后需要打印日志记录。
客户端:通过代理商获取计费服务并打印。
4.3. 公共接口(FeeInterface)
package cn.yzstu.proxy.feeinterface;
public interface FeeInterf {
void doFee();
}
4.4. 服务商
package cn.yzstu.proxy.service;
import cn.yzstu.proxy.feeinterface.FeeInterf;
/** * @author baldwin */
public class FeeService implements FeeInterf {
public FeeService() {
System.out.println("新建一个FeeService!!!");
}
/** *@描述 服务商中的实际服务 *@方法名 doFee *@参数 [] *@返回值 void *@创建人 Baldwin *@创建时间 2020/5/11 *@修改人和其它信息 */
public void doFee() {
System.out.println("在Service中获取计费成功!!!");
}
}
4.5. 代理商
package cn.yzstu.proxy.proxy;
import cn.yzstu.proxy.feeinterface.FeeInterf;
import cn.yzstu.proxy.service.FeeService;
/** * @author baldwin */
public class FeeProxy implements FeeInterf {
/** * 代理商中与服务商接触 * */
private FeeService feeService = new FeeService();
public void doFee() {
// 执行预操作
preFee();
// 通过实际服务商进行调起计费
feeService.doFee();
// 进行后操作
postFee();
}
/** *@描述 请求Fee的预操作 *@方法名 preFee *@参数 [] *@返回值 void *@创建人 Baldwin *@创建时间 2020/5/11 *@修改人和其它信息 */
private void preFee(){
System.out.println("请求Fee之前的操作完成!!!");
}
/** *@描述 计费请求结束后的操作 *@方法名 postFee *@参数 [] *@返回值 void *@创建人 Baldwin *@创建时间 2020/5/11 *@修改人和其它信息 */
private void postFee(){
System.out.println("请求Fee之后的操作完成!!!");
}
}
4.6. 客户端
package cn.yzstu.proxy;
import cn.yzstu.proxy.proxy.FeeProxy;
public class Client {
public static void main(String[] args) {
// 客户端中没有直接接触FeeService
FeeProxy feeProxy = new FeeProxy();
// 客户端调起计费
feeProxy.doFee();
}
}
4.7. 运行结果
/usr/lib/jvm/java-8-openjdk-amd64/bin/java ××××
新建一个FeeService!!!
请求Fee之前的操作完成!!!
在Service中获取计费成功!!!
请求Fee之后的操作完成!!!
Process finished with exit code 0
4.8. 小总结
代理模式的核心点就是客户端不与服务商接触。
5. 代理模式的一般场景
5.1. 服务安全
一般为了安全考虑,都不会让客户端接触核心服务,这样就可以用一个代理将客户端与核心服务隔离开。
5.2. 智能处理
就像我们刚才那样,可以在操作服务商的方法之前和之后都可以添加操作。在工作中的表现有一个就是操作数据库,可以在服务之前建立数据库连接,服务结束后断开连接。
5.3. 虚拟服务
这种情况在我们访问网页的时候经常发生,比如们要访问一个图片,但是这个图片非常大,可能会加载很久,这时就可以通过虚拟代理来先提供一个缩略图,等图片加载完成后再将原图展示。
5.4. 等等
6. 总结
其实最近在回顾之前写的关于设计模式的文章,我发现了一个问题,我所有的相关文章都是只有某一个模式的实例,这样其实显得文章很没有内容,就像代理模式,我在实际设计代码的过程中肯定不能单独使用,一定是配合其他设计模式一起使用,所以在考虑要不要出一个设计模式配合使用的合集。
代理模式也是一个很常用的模式,SpringAOP中大量使用了代理模式。
往期好文: